随笔 - 165, 文章 - 0, 评论 - 18, 阅读 - 22万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

【转】C# / Extension 扩展方法

Posted on   火冰·瓶  阅读(326)  评论(0编辑  收藏  举报

扩展方法简介
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C#、F# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法没有明显区别。

详见微软官方文档的定义和使用说明:扩展方法(C# 编程指南)

编写方法
定义一个测试用的类,并包含一个成员方法:

1
2
3
4
5
6
7
public class Module
{
    public void Func1()
    {
        // TODO..
    }
}

  


定义一个静态类,编写一个静态方法,用于扩展Module类:

1
2
3
4
5
6
7
public static class TestExtension
{
    public static void Func2(this Module mod)
    {
        // TODO..
    }
}

  


调用测试:

1
2
3
4
5
6
public void Test()
{
    var mod = new Module();
    mod.Func1();
    mod.Func2();
}

  


扩展方法的注意点:
* 需要写在一个静态类中
* 必须是一个静态方法
* 通过第一个参数和this关键字指定扩展的目标类型
* 不同类型的扩展方法不一定要写在同一个类中

如上所示,对Module类进行扩展后,可以和调用原生方法一样,调用扩展方法,在上层使用感受不到区别。通过这种方式,可以很好的对C#原生的类型,和不开源的第三方库,增加额外需求的、符合自己书写习惯的或者有效提高项目开发效率的新接口。

自己项目中实例

1.定义主体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ResChildBase
{
    [Key]
    [ForeignKey("ResBaseInfo")]
    [Column(TypeName = "char(36)")]
    public Guid ID { get; set; }
 
    public virtual ResBaseInfo ResBaseInfo { get; set; }
 
 
    /// <summary>
    /// 多语言的详情描述集合
    /// </summary>
    [NotMapped]
    public List<Description> DescriptionCollection { get; set; }
 
 
 
    /// <summary>
    /// 获取某个语言的详情描述(这种是传统的方式,定义到方法上。但对于类库中的类无法操作)
    /// </summary>
    /// <param name="lang">多种语言的枚举</param>
    /// <returns></returns>
    public Description CurDescription(Lang lang) {
        return DescriptionCollection.Find(g=>g.Language.Equals(lang));
    }
}

  2.书写扩展方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static class EntityExtension
{
    /// <summary>
    /// 获取指定语言的详情
    /// </summary>
    /// <param name="list"></param>
    /// <param name="lang">枚举类型的语言</param>
    /// <returns></returns>
    public static Description GetDesc(this List<Description> list, Lang lang)
    {
        return list.Find(g=>g.Language.Equals(lang));
    }
 
 
    /// <summary>
    /// 获取指定语言的详情
    /// </summary>
    /// <param name="list"></param>
    /// <param name="lang">字符串类型的语言</param>
    /// <returns></returns>
    public static Description GetDesc(this List<Description> list, string lang)
    {
        return  list.Find(g => g.Language.ToString().Equals(lang));
    }
}

  3.使用

1
2
3
4
5
6
7
//hotel是继承自ResChildBase的子类
Description des= hotel.CurDescription(Lang.CN);
 
 
//或者
//在这个View中,Model的类型是继承自ResChildBase的子类
@await Html.PartialAsync("~/Views/Description/_DescriptionDetailView.cshtml", Model.DescriptionCollection.GetDesc("CN"))

  

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示