将各个单独的操作链接在一起形成了一个管道

时间:2021-12-12 02:57:26

你不能转变类型自己, 因为是别人的代码。

对付C#1和C#2中的静态要领,扩展要领是一种更优雅的解决方案。

语法

并不是任何要领都能作为扩展要领使用—— 它必需具有以下特征:

它必需在一个非嵌套的、 非泛型的静态类中( 所以必需是一 个静态要领);

它至少要有 一个参数;

第一个参数必需附加 this 关键字作为前缀;

第一个参数不能有其他任何修饰 符(好比out或ref);

第一个参数的类型不能是指针类型。

我们来试着给Stream类写一个扩展要领:

public static class StreamUtil { const int bufferSize = 8192; public static void CopyToo(this Stream inputStream, Stream outPutStream) { var buffer = new byte[bufferSize]; int read; while ((read=inputStream.Read(buffer,0,buffer.Length))>0) { outPutStream.Write(buffer,0,read); } } public static byte[] ReadFull(this Stream input) { using (MemoryStream stream=new MemoryStream()) { CopyToo(input,stream); return stream.ToArray(); } } }

扩展要领必需在*的静态类中进行声明,不能是嵌套的静态类。

扩展要领假装本身是另一个类的实例要领,来看看如何使用:

static void Main(string[] args) { WebRequest request = WebRequest.Create("https://www.baidu.com"); using (WebResponse response = request.GetResponse()) using (var resStream = response.GetResponseStream()) using(var outPut=File.Open(@"C:\Users\jianxin\Desktop\test.txt",FileMode.Open)) { resStream.CopyToo(outPut); } Console.WriteLine("done!"); Console.ReadKey(); }

之所以吧CopyTo改成CopyToo是因为Stream此刻已经实现了这个扩展要领了。如果和实例要领同名,则不会去挪用这个扩展要领。

一些道理

一般来说,如果你在一个东西后面挪用这个东西的成员好比要领,编译器会首先从它的实例成员中去寻找,如果没有找到,他会在引入的定名空间里面去寻找合适的扩展要领。

为了决定是否使用 一个扩展要领, 编译器必需能区分扩展要领与某静态类中刚好具有合适签名的其他要领。 为此,, 它会查抄类和要领是否具有System.Runtime.CompilerServices.ExtensionAttribute 这个特性, 它是.NET 3. 5 新增的。 但是,编译器不查抄特性来自哪个措施集。这意味着你可以在C#2或早前的版本中本身编写一个这个特性类来满足编译器的这种搜索计谋。但是,谁特么还在用C#2或1呢?如果遇到多个合适的版本,还是会用“更好的选择”原则来选用最合适的那一个。

在空引用上面挪用扩展要领

在空引用上面挪用要领会导致NullRefrenceException的异常。但是可以挪用扩展要领而不会导致异常。

public static class NullUtil { public static bool IsNull(this object obj) {return obj==null;
}
}

static void Main(string[] args) { object obj = null; Console.WriteLine(obj.IsNull());//true obj = new object(); Console.WriteLine(obj.IsNull());//false Console.ReadKey(); }

如果IsNull是一个实例要领那么会引发NullRefrenceException,但是扩展要领不会,可以试一试,很爽。这个写法与string.IsNullOrEmpty()形成了鲜明的比拟。

Enumerable

LINQ差不久不多全部的成果都是用Enumerable和Queryable的扩展要领来得到的。

Enumerable中有一个不是扩展要领:Range

var collection = Enumerable.Range(0, 10); foreach (int item in collection) { Console.WriteLine(item); }

讲这个例子并不是因为它很特殊,是因为它的一个特性:延迟执行 。Range要领并不会真的结构含有适当数字的列表,它只是在得当的时间生成那些数。 换言之,结构的可枚举的实例并不会做大部分事情。 它只是将对象筹备好, 使数据能在适当的位置以一种“just-in-time” 的方法供给。 这称为延迟执行, 是LINQ的一个核心部分。

可以按照一个可枚举的实例返回另一个可枚举的实例,这在LINQ中是很常见的:collection.Reverse();

缓冲和流式技术