β

c#中的扩展方法

逝去日子的博客 106 阅读

扩展方法 使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。

如何定义自己的扩展方法呢?下面给出扩展方法所必须具备的特征:

  1. 它必须在一个非嵌套的,非泛型的静态类中(所以必须是一个静态方法)
  2. 它至少需要一个参数
  3. 第一个参数必须附加this关键字作为前缀
  4. 第一个参数不能有其他的任何修饰符(如ref或out)
  5. 第一个参数的类型不能是指针类型

就这么多要求,方法可以使泛型的,可以返回一个值,除第一个参数外其他参数可以附加ref或out参数.可以随同一个迭代快实现,可以是一个分部类的一部分,可以使用可空类型,可以是任何方法.
下面来举三个小例子来说明一下扩展方法的定义和调用:

public static class StreamUtil
    {
        const int BufferSize = 8192;
        public static void MyCopyTo(this Stream input, Stream output)
        {
            byte[] buffer = new byte[BufferSize];
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, read);
            }
        }
        public static byte[] ReadFully(this Stream input)
        {
            using (MemoryStream tempstream = new MemoryStream())
            {
                MyCopyTo(input, tempstream);
                return tempstream.ToArray();
            }
        }
    }


    class Program
    {

        static void Main(string[] args)
        {
            WebRequest request = WebRequest.Create("http://www.baidu.com/");
            using (WebResponse response = request.GetResponse())
            using (Stream responseStream = response.GetResponseStream())
            using (FileStream output = File.Create("response.dat"))
            {
                responseStream.MyCopyTo(output);
            }
    }

可以看到,在调用的时候,并没有任何迹象来表明我们调用的是一个扩展方法.而不是Stream类的一个普通的实例方法.不过,我们可以通过VS来提示我们调用的是不是一个扩展方法.
下面在给出一个例子

//学生类
    public class Student
    {
        public string  Name { get; set; }

        public int Age { get; set; }

        public string City { get; set; }
    }

    //集合类
    public class StudentList:List<Student>
    {
        public StudentList()
        {
            this.Add(new Student() { Name = "张三", Age = 22, City = "北京" });
            this.Add(new Student() { Name = "李四", Age = 23, City = "北京" });
            this.Add(new Student() { Name = "王武", Age = 24, City = "南京" });
            this.Add(new Student() { Name = "何二", Age = 25, City = "南京" });
        }
    }

    //扩展方法
    //根据城市名称返回学生列表
    public static class StuListExtension
    {
        public static IEnumerable<Student> GetStudentByCity(this List<Student> stuList, string city)
        {   
            var result = stuList.Where(s => s.City == city).Select(s => s);
            return result;
        }
    }

在Main方法中调用

class Program
    {
        static void Main(string[] args)
        {            
            StudentList StudentSource = new StudentList();
            IEnumerable<Student> bjStudents = StudentSource.GetStudentByCity("北京");
            Console.WriteLine("北京的学生列表:");
            foreach (var s in bjStudents)
            {
                Console.WriteLine(string.Format("姓名:{0}  年龄:{1}  城市:{2}", s.Name, s.Age, s.City));
            }
            Console.ReadKey();
        }
    }

还有一个例子,这个是先定义了一个string数组,然后通过MyWhere来返回大于”e”的元素

public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
        {
            if (source==null||predicate==null)
            {
                throw new ArgumentNullException();
            }
            return WhereImpl(source, predicate);
        }
        private static IEnumerable<T> WhereImpl<T>(IEnumerable<T> source, Func<T, bool> predicate)
        {
            foreach (T item in source)
            {
                if (predicate(item))
                {
                    yield return item;
                }
            }
        }
//下面是如何调用
string[] strs = new string[]
{
    "a","b","c","d","e","f","g"
};
foreach (string s in strs.MyWhere(s => s.CompareTo("e") > 0))
{
     Console.WriteLine(s.ToString());
}
作者:逝去日子的博客
大巧无工,重剑无锋
原文地址:c#中的扩展方法, 感谢原作者分享。

发表评论