在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到。
继承的有关特性的使用所带来的问题:对象的继承关系实在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。
当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写它或被其他更适合的类替换,这种依赖关系限制了灵活性并最终限制了复用性。替代继承特性的方式,较多的会采用 合成/聚合复用原则,“合成/聚合复用原则”:尽量使用合成/聚合,尽量不要使用类继承。
如果在新类型的对象应当携带有关额外行为的细节,在使用继承特性时,有时可能不太适合,例如:处理指类型,密封类,或者接口时。在面对这些要求时,我们有时候会写一些静态类包含一些静态方法。但是过多的静态方法会造成额外的不必要的开销。
一.扩展方法概述:
面对以上的有关“继承”的问题,以及在面对项目的一些需求时,我们需要解决这些问题的方式就是“扩展方法”。在C#3.0中引入了“扩展方法”,既有静态方法的优点,又使调用它们的代码的可读性得到了提高。在使用扩展方法时,可以像调用实例方法那样调用静态方法。
1.扩展方法的基本原则:
(1).C#只支持扩展方法,不支持扩展属性、扩展事件、扩展操作符等。
(2).扩展方法(第一个参数前面是this的方法)必须在非泛型的静态类中声明,扩展方法必须有一个参数,而且只有第一个参数使用this标记。
(3).C#编译器查找静态类中的扩展方法时,要求这些静态类本身必须具有文件作用域。
(4).C#编译要求“导入”扩展方法。(静态方法可以任意命名,C#编译器在寻找方法时,需要花费时间进行查找,需要检查文件作用域中的所有的静态类,并扫描它们的所有静态方法来查找一个匹配)
(5).多个静态类可以定义相同的扩展方法。
(6).用一个扩展方法扩展一个类型时,同时也扩展了派生类型。
2.扩展方法声明:
(1).必须在一个非嵌套的、非泛型型的静态类中(所以必须是一个静态方法)
(2).至少有一个参数。
(3).第一个参数必须附加this关键字做前缀。
(4).第一个参数不能有其他任何修饰符(如ref或out)。
(5).第一个参数的类型不能是指针类型。
以上的两个分类说明中,对扩展方法的基本特性和声明方式做了一个简单的介绍,有关扩展方法的使用方式,会在后面的代码样例中进行展示,再次就不再多做说明。
二.扩展方法原理解析:
“扩展方法”是C#独有的一种方法,在扩展方法中会使用ExtensionAttribute这个attribute。
C#一旦使用this关键字标记了某个静态方法的第一个参数,编译器就会在内部向该方法应用一个定制的attribute,这个attribute会在最终生成的文件的元数据中持久性的存储下来,此属性在System.Core dll程序集中。
任何静态类只要包含了至少一个扩展方法,它的元数据中也会应用这个attribute,任何一个程序集包含了至少一个符合上述特点的静态类,它的元数据也会应用这个attribute。如果代码嗲用了一个不存在的实例方法,编译器会快速的扫描引用的所有程序集,判断它们哪些包含了扩展方法,然后,在这个程序集中,可以扫描包含了扩展方法的静态类。
如果同一个命名空间中的两个类含有扩展类型相同的方法,就没有办法做到只用其中一个类中的扩展方法。为了通过类型的简单名称(没有命名控件前缀)来使用类型,可以导入该类型所有在的命名空间,但这样做的时候,你没有办法阻止那个命名空间中的扩展方法也被导入进来。
三..NET3.5的扩展方法Enumerable和Queryable:
在框架中,扩展方法最大的用途就是为LINQ服务,框架提供了辅助的扩展方法,位于System.Linq命名空间下的Enumerable和Queryable类。Enumerable大多数扩展是IEnumerable8742468051c85b06f0a0af9e3e506b5c,Queryable大大多数扩展是IQueryable8742468051c85b06f0a0af9e3e506b5c。
1.Enumerable类中的常用方法
(1).Range():一个参数是起始数,一个是要生成的结果数。
public static IEnumerable<int> Range(int start, int count) { long max = ((long)start) + count - 1; if (count < 0 || max > Int32.MaxValue) throw Error.ArgumentOutOfRange("count"); return RangeIterator(start, count); } static IEnumerable<int> RangeIterator(int start, int count) { for (int i = 0; i < count; i++) yield return start + i; }
(2).Where():对集合进行过滤的一个方式,接受一个谓词,并将其应用于原始集合中的每个元素。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { if (source == null) throw Error.ArgumentNull("source"); if (predicate == null) throw Error.ArgumentNull("predicate"); if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate); if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate); if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate); return new WhereEnumerableIterator<TSource>(source, predicate); } public WhereEnumerableIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate) { this.source = source; this.predicate = predicate; }
以上分别介绍了Range()和Where()两个方法,该类中还主要包含select()、orderby()等等方法。
2.Queryable类中的常用方法:
(1).IQueryable接口:
/// <summary> /// 提供对未指定数据类型的特定数据源的查询进行计算的功能。 /// </summary> /// <filterpriority>2</filterpriority> public interface IQueryable : IEnumerable { /// <summary> /// 获取与 <see cref="T:System.Linq.IQueryable"/> 的实例关联的表达式目录树。 /// </summary> /// /// <returns> /// 与 <see cref="T:System.Linq.IQueryable"/> 的此实例关联的 <see cref="T:System.Linq.Expressions.Expression"/>。 /// </returns> Expression Expression { get; } /// <summary> /// 获取在执行与 <see cref="T:System.Linq.IQueryable"/> 的此实例关联的表达式目录树时返回的元素的类型。 /// </summary> /// /// <returns> /// 一个 <see cref="T:System.Type"/>,表示在执行与之关联的表达式目录树时返回的元素的类型。 /// </returns> Type ElementType { get; } /// <summary> /// 获取与此数据源关联的查询提供程序。 /// </summary> /// /// <returns> /// 与此数据源关联的 <see cref="T:System.Linq.IQueryProvider"/>。 /// </returns> IQueryProvider Provider { get; } }
(2).Where():
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) { if (source == null) throw Error.ArgumentNull("source"); if (predicate == null) throw Error.ArgumentNull("predicate"); return source.Provider.CreateQuery<TSource>( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); }
(3).Select():
public static IQueryable<TResult> Select<TSource,TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) { if (source == null) throw Error.ArgumentNull("source"); if (selector == null) throw Error.ArgumentNull("selector"); return source.Provider.CreateQuery<TResult>( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector) } )); }
以上是对扩展方法中两个类进行了一个简单的解析。
四.扩展方法实例:
由于扩展方法实际是对一个静态方法的调用,所以CLR不会生成代码对调用方法的表达式的值进行null值检查
1.异常处理代码:
/// <summary> /// 为参数验证提供有用的方法 /// </summary> public static class ArgumentValidator { /// <summary> /// 如果argumentToValidate为空,则抛出一个ArgumentNullException异常 /// </summary> public static void ThrowIfNull(object argumentToValidate, string argumentName) { if (null == argumentName) { throw new ArgumentNullException("argumentName"); } if (null == argumentToValidate) { throw new ArgumentNullException(argumentName); } } /// <summary> /// 如果argumentToValidate为空,则抛出一个ArgumentException异常 /// </summary> public static void ThrowIfNullOrEmpty(string argumentToValidate, string argumentName) { ThrowIfNull(argumentToValidate, argumentName); if (argumentToValidate == string.Empty) { throw new ArgumentException(argumentName); } } /// <summary> /// 如果condition为真,则抛出ArgumentException异常 /// </summary> /// <param name="condition"></param> /// <param name="msg"></param> public static void ThrowIfTrue(bool condition, string msg) { ThrowIfNullOrEmpty(msg, "msg"); if (condition) { throw new ArgumentException(msg); } } /// <summary> /// 如果指定目录存在该文件则抛出FileNotFoundException异常 /// </summary> /// <param name="fileSytemObject"></param> /// <param name="argumentName"></param> public static void ThrowIfDoesNotExist(FileSystemInfo fileSytemObject, String argumentName) { ThrowIfNull(fileSytemObject, "fileSytemObject"); ThrowIfNullOrEmpty(argumentName, "argumentName"); if (!fileSytemObject.Exists) { throw new FileNotFoundException("'{0}' not found".Fi(fileSytemObject.FullName)); } } public static string Fi(this string format, params object[] args) { return FormatInvariant(format, args); } /// <summary> /// 格式化字符串和使用<see cref="CultureInfo.InvariantCulture">不变的文化</see>. /// </summary> /// <remarks> /// <para>这应该是用于显示给用户的任何字符串时使用的“B”>“B”>“”。它意味着日志 ///消息,异常消息,和其他类型的信息,不使其进入用户界面,或不会 ///无论如何,对用户都有意义;).</para> /// </remarks> public static string FormatInvariant(this string format, params object[] args) { ThrowIfNull(format, "format"); return 0 == args.Length ? format : string.Format(CultureInfo.InvariantCulture, format, args); } /// <summary> /// 如果时间不为DateTimeKind.Utc,则抛出ArgumentException异常 /// </summary> /// <param name="argumentToValidate"></param> /// <param name="argumentName"></param> public static void ThrowIfNotUtc(DateTime argumentToValidate, String argumentName) { ThrowIfNullOrEmpty(argumentName, "argumentName"); if (argumentToValidate.Kind != DateTimeKind.Utc) { throw new ArgumentException("You must pass an UTC DateTime value", argumentName); } } }
2.枚举扩展方法:
public static class EnumExtensions { /// <summary> /// 获取名字 /// </summary> /// <param name="e"></param> /// <returns></returns> public static string GetName(this Enum e) { return Enum.GetName(e.GetType(), e); } /// <summary> /// 获取名字和值 /// </summary> /// <param name="enumType">枚举</param> /// <param name="lowerFirstLetter">是否转化为小写</param> /// <returns></returns> public static Dictionary<string, int> GetNamesAndValues( this Type enumType, bool lowerFirstLetter) { //由于扩展方法实际是对一个静态方法的调用,所以CLR不会生成代码对调用方法的表达式的值进行null值检查 ArgumentValidator.ThrowIfNull(enumType, "enumType"); //获取枚举名称数组 var names = Enum.GetNames(enumType); //获取枚举值数组 var values = Enum.GetValues(enumType); var d = new Dictionary<string, int>(names.Length); for (var i = 0; i < names.Length; i++) { var name = lowerFirstLetter ? names[i].LowerFirstLetter() : names[i]; d[name] = Convert.ToInt32(values.GetValue(i)); } return d; } /// <summary> /// 转换为小写 /// </summary> /// <param name="s"></param> /// <returns></returns> public static string LowerFirstLetter(this string s) { ArgumentValidator.ThrowIfNull(s, "s"); return char.ToLowerInvariant(s[0]) + s.Substring(1); } }
五.总结:
在本文中,主要对扩展方法进行了一些规则说明、声明方式,使用方式,以及对扩展方法的意义和扩展方法的原理进行了简单的解答。并在本文的最后给了一个枚举的扩展方法代码。
以上就是C#的扩展方法解析的内容,更多相关内容请关注PHP中文网(www.php.cn)!

C#和.NET通过不断的更新和优化,适应了新兴技术的需求。1)C#9.0和.NET5引入了记录类型和性能优化。2).NETCore增强了云原生和容器化支持。3)ASP.NETCore与现代Web技术集成。4)ML.NET支持机器学习和人工智能。5)异步编程和最佳实践提升了性能。

c#.netissutableforenterprise-levelapplications withemofrosoftecosystemdueToItsStrongTyping,richlibraries,androbustperraries,androbustperformance.however,itmaynotbeidealfoross-platement forment forment forment forvepentment offependment dovelopment toveloperment toveloperment whenrawspeedsportor whenrawspeedseedpolitical politionalitable,

C#在.NET中的编程过程包括以下步骤:1)编写C#代码,2)编译为中间语言(IL),3)由.NET运行时(CLR)执行。C#在.NET中的优势在于其现代化语法、强大的类型系统和与.NET框架的紧密集成,适用于从桌面应用到Web服务的各种开发场景。

C#是一种现代、面向对象的编程语言,由微软开发并作为.NET框架的一部分。1.C#支持面向对象编程(OOP),包括封装、继承和多态。2.C#中的异步编程通过async和await关键字实现,提高应用的响应性。3.使用LINQ可以简洁地处理数据集合。4.常见错误包括空引用异常和索引超出范围异常,调试技巧包括使用调试器和异常处理。5.性能优化包括使用StringBuilder和避免不必要的装箱和拆箱。

C#.NET应用的测试策略包括单元测试、集成测试和端到端测试。1.单元测试确保代码的最小单元独立工作,使用MSTest、NUnit或xUnit框架。2.集成测试验证多个单元组合的功能,常用模拟数据和外部服务。3.端到端测试模拟用户完整操作流程,通常使用Selenium进行自动化测试。

C#高级开发者面试需要掌握异步编程、LINQ、.NET框架内部工作原理等核心知识。1.异步编程通过async和await简化操作,提升应用响应性。2.LINQ以SQL风格操作数据,需注意性能。3..NET框架的CLR管理内存,垃圾回收需谨慎使用。

C#.NET面试问题和答案包括基础知识、核心概念和高级用法。1)基础知识:C#是微软开发的面向对象语言,主要用于.NET框架。2)核心概念:委托和事件允许动态绑定方法,LINQ提供强大查询功能。3)高级用法:异步编程提高响应性,表达式树用于动态代码构建。

C#.NET是构建微服务的热门选择,因为其生态系统强大且支持丰富。1)使用ASP.NETCore创建RESTfulAPI,处理订单创建和查询。2)利用gRPC实现微服务间的高效通信,定义和实现订单服务。3)通过Docker容器化微服务,简化部署和管理。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能