c#中的扩展方法

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

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

它必须在一个非嵌套的,非泛型的静态类中(所以必须是一个静态方法)

  1. 它至少需要一个参数
  2. 第一个参数必须附加this关键字作为前缀
  3. 第一个参数不能有其他的任何修饰符(如ref或out)
  4. 第一个参数的类型不能是指针类型
  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#中的扩展方法》上有1条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注