zoukankan      html  css  js  c++  java
  • 扩展方法

    扩展方法可以理解为现有的类型(现有类型可以为自定义的类型和.Net 类库中的类型)扩展(添加)应该附加到该类型中的方法
     
    在没有扩展方法之前,如果我们想为一个已有类型自定义自己逻辑的方法时,我们必须自定义一个新的类型来继承已有类型的方式来添加方法
     
    扩展方法必须具备下面的规则:
    • 它必须在一个非嵌套、非泛型的静态类中
    • 它至少要有一个参数
    • 第一个参数必须加上this关键字作为前缀(第一个参数类型也称为扩展类型,即指方法对这个类型进行扩展)
    • 第一个参数不能用其他任何修饰符(如不能使用ref out等修饰符)
    • 第一个参数的类型不能是指针类型
     
    演示代码: 
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CustomNamesapce
    {
        using EventDemo;
    
        public static class CustomExtensionClass
        {
            /// <summary>
            /// 扩展方法定义
            /// </summary>
            /// <param name="per"></param>
            public static void Print(this Person per)
            {
                Console.WriteLine("调用的是不同命名空间下扩展方法输出,姓名为: {0}", per.Name);
            }
    
            /// <summary>
            /// 扩展方法定义
            /// </summary>
            /// <param name="per"></param>
            public static void Print(this Person per, string s)
            {
                Console.WriteLine("调用的是不同命名空间下扩展方法输出,姓名为: {0}, 附加字符串为{1}", per.Name, s);
            }
    
        }
    }
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    
    namespace EventDemo
    {
        // 要使用不同命名空间的扩展方法首先要添加该命名空间的引用
        using CustomNamesapce;
        class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person { Name = "Learning hard" };
                // 当类型中包含了实例方法时,VS中的智能提示就只会列出实例方法,而不会列出扩展方法
                // 当把实例方法注释掉之后,VS的智能提示中才会列出扩展方法,此时编译器在Person类型中找不到实例方法
                // 所以首先从当前命名空间下查找是否有该名字的扩展方法,如果找到不会去其他命名空间中查找了
                // 如果在当前命名空间中没有找到,则会到导入的命名空间中再进行查找
                p.Print();
                p.Print("Hello");
                Console.Read();
            }
        }
    
        // 自定义类型
        public class Person
        {
            public string Name { get; set; }
    
            // 当类型中的实例方法
            ////public void Print()
            ////{
            //// Console.WriteLine("调用实例方法输出,姓名为: {0}", Name);
            ////}
        }
    
        // 当前命名空间下的扩展方法定义
        public static class Extensionclass
        {
            /// <summary>
            /// 扩展方法定义
            /// </summary>
            /// <param name="per"></param>
            public static void Print(this Person per)
            {
                Console.WriteLine("调用的是同一命名空间下的扩展方法输出,姓名为: {0}", per.Name);
            }
        }
    }
    View Code

    大家都知道在C#中,在空引用上调用实例方法是会引发NullReferenceException异常的,但是可以在空引用上调用扩展方法,下面看一段演示代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventDemo
    {
        namespace ExtensionDefine
        {
            /// <summary>
            /// 扩展方法定义
            /// </summary>
            public static class NullExten
            {
                // 此时扩展的类型为object,这里我是故意用object类型的
                // 如果是为了演示,当我们为一个类型定义扩展方法时,应尽量扩展具体类型,如果扩展其基类的话
                // 则所有继承于基类的类型都将具有该扩展方法,这样对其他类型来说就进行了“污染
                // 子所以形成了污染,是因为我们定义的扩展方法的意图本来只想扩展某个子类。
                // 其实下面这个方法我的意图只是想扩展string类型的,所以更好的定义方法如下:
                //public static bool isNull(this string str)
                //{
                // return str == null;
                //}
    
                // 不规范定义扩展方法的方式
                public static bool IsNull(this object obj)
                {
                    return obj == null;
                }
            }
        }
    }
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    
    namespace EventDemo
    {
        // 必须引入扩展方法定义的命名空间
        using ExtensionDefine;
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("空引用上调用扩展方法演示:");
                string s = null;
    
                // 在该程序中要使用扩展方法必须通过using来引用
                // 在空引用上调用扩展方法不会发生NullReferenceException异常
                // 之所以不会出现异常,是因为在空引用上调用扩展方法,对于编译器而言只是把空引用s当成参数传入静态方法中而已
                // 对于编译器来说,s.IsNull()的调用等效于下面的代码
                //Console.WriteLine("字符串S为空字符串:{0}", NullExten.IsNull(s));
    
                Console.WriteLine("字符串S为空字符串:{0}", s.IsNull());
                Console.ReadKey();
            }
        }
    }
    View Code
  • 相关阅读:
    【Jsoi2010】连通数
    【CQOI2009】中位数图
    【POJ 1151】 Altlantis
    【2017省中集训】 香港记者
    【AHOI2009】中国象棋
    【SCOI 2009】 Windy数
    【HDU 4722】 Good Numbers
    【HDU 2089】 不要62
    BZOJ3129 SDOI2013方程(容斥原理+扩展lucas)
    BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)
  • 原文地址:https://www.cnblogs.com/scmail81/p/8678658.html
Copyright © 2011-2022 走看看