服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#泛型设计需要注意的一个小陷阱

C#泛型设计需要注意的一个小陷阱

2022-07-11 08:28詹姆斯.辛 C#

这篇文章主要给大家介绍了关于C#泛型设计需要注意的一个小陷阱,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

距离上次发表博客已经有几年了. 对于没能坚持更新博客,实在是感觉到甚是惭愧.

闲言少叙, 直接切入主题.

什么是泛型

我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。

但泛型就简单吗?当然不是,继续往下看..

背景

最近一直在对于公司一个网络通信服务程序使用.net core 进行重构.重构的目的有两个:一是让程序能够跨平台运行. 二是优化程序代码结构是程序的可维护性有所提升.  重构的过程主要由我来设计底层的架构. 在这个过程中,由于我对C# 泛型的理解还不够深入,所以在这个方面我就犯了个错误. 希望本文能把我犯的这个错误阐述清楚, 如果能帮助园里其他朋友避免这个问题当然是最好的了.

早前的设计

先用一张图来描述早前的代码结构

C#泛型设计需要注意的一个小陷阱

Singleton<T> :是一个单例的基类, 用来实现单例模式.

Base<T> : 则是一个基础类,它有一些静态的属性和方法(例如访问Redis,kafka,数据库等). 这些属性和方法提供给 Child1 和 Child2 去使用.

Child1 和Child2: 相当于不同模块的业务逻辑实现.

 我期望的结果是Base<T>里面的静态成员在整个程序运行期间只有一份.

代码的实现

Singleton

?
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
public abstract class Singleton<T> where T : new()
 {
  /// <summary>
  /// 锁定对象
  /// </summary>
  private static readonly object locker = new object();
  /// <summary>
  /// T 的实例
  /// </summary>
  static T instance = default(T);
  /// <summary>
  /// T 的实例
  /// </summary>
  public static T Instance
  {
   get
   {
    if (null == instance)
    {
     lock (locker)
     {
      if (null == instance)
      {
       instance = new T();
      }
     }
    }
    return instance;
   }
  }
 }

Base

?
1
2
3
4
5
6
7
8
9
public class Base<T> : Singleton<T> where T : new()
{
 protected static object Object { set; get; }
 
 static Base()
 {
  Object = new object();
 }
}

Child1 和Child2

?
1
2
3
4
5
6
7
public class Child1 : Base<Child1>
{
}
 
public class Child2 : Base<Child2>
{
}

我以为 Base的静态构造函数只会执行一次. 可是当我在程序里使用 Child1.Instance Child2.Instance 时发现, Base的静态构造函数被执行了2次. 那么Child1.Instance的Object和Child2.Instance的Object对象一定不是同一个.

那么问题出现在什么地方了呢? 答案其实挺简单的:系统认为 Base<Child1> Base<Child2>并不相同. 相当于在系统里定义了Base_Child1 和Base_Child2两个类. 如果我们这么理解这个问题 ,那么Base的静态构造函数被执行了2次就不难理解了.(我觉得我已经把这个问题的成因描述清楚了,如果您没理解,欢迎在下面评论.)

如果要达到我设计的目标应该怎么做呢?

修正的设计

还是先上类图.

C#泛型设计需要注意的一个小陷阱

Base:

?
1
2
3
4
5
6
7
8
9
public class Base
{
 protected static object Object { set; get; }
 
 static Base()
 {
  Object = new object();
 }
}

Singleton:

?
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
public abstract class Singleton<T>: Base where T : new()
{
  /// <summary>
  /// 锁定对象
  /// </summary>
  private static readonly object locker = new object();
  /// <summary>
  /// T 的实例
  /// </summary>
  static T instance = default(T);
  /// <summary>
  /// T 的实例
  /// </summary>
  public static T Instance
  {
   get
   {
    if (null == instance)
    {
     lock (locker)
     {
      if (null == instance)
      {
       instance = new T();
      }
     }
    }
    return instance;
   }
  }
}

Child1 和Child2:

?
1
2
3
4
5
6
7
public class Child1 : Singleton<Child1>
{
}
 
public class Child2 : Singleton<Child2>
{
}

由Singleton 来继承Base.然后Child1 和Child2来继承Singleton. 这样问题就都解决了.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.cnblogs.com/james2010/p/10483645.html

延伸 · 阅读

精彩推荐
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127282021-11-25
  • C#C#实现将Doc文档转换成rtf格式的方法示例

    C#实现将Doc文档转换成rtf格式的方法示例

    这篇文章主要介绍了C#实现将Doc文档转换成rtf格式的方法,结合实例形式分析了C#针对word文件的读取及文档格式转换相关操作技巧,需要的朋友可以参考下...

    a7719485248052022-01-12
  • C#详解C# 匿名对象(匿名类型)、var、动态类型 dynamic

    详解C# 匿名对象(匿名类型)、var、动态类型 dynamic

    随着C#的发展,该语言内容不断丰富,开发变得更加方便快捷,C# 的锋利尽显无疑。下面通过本文给大家分享C# 匿名对象(匿名类型)、var、动态类型 dyn...

    DW0396142022-01-21
  • C#C# 7.0之ref locals and returns(局部变量和引用返回)

    C# 7.0之ref locals and returns(局部变量和引用返回)

    这篇文章主要介绍了C# 7.0之ref locals and returns,即局部变量和引用返回,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    GuZhenYin5832021-12-29
  • C#C#实现餐厅管理系统

    C#实现餐厅管理系统

    这篇文章主要为大家详细介绍了C#实现餐厅管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    malloc_w10032022-03-09
  • C#轻松学习C#的运算符

    轻松学习C#的运算符

    轻松学习C#的运算符,对C#的运算符感兴趣的朋友可以参考本篇文章,帮助大家更灵活的运用C#的运算符。...

    丿木呈广予口贝5982021-11-03
  • C#在winform下实现左右布局多窗口界面的方法之续篇

    在winform下实现左右布局多窗口界面的方法之续篇

    这篇文章主要介绍了在winform下实现左右布局多窗口界面的方法之续篇 的相关资料,需要的朋友可以参考下...

    梦在旅途6512021-11-14
  • C#Json操作库DynamicJson使用指南

    Json操作库DynamicJson使用指南

    本文给大家分享的是专门为.NET程序员开发的Json操作库DynamicJson,其源码非常简单,仅仅只有400行代码,一个对应的class类,目前只支持.NET 4.0以上的.NET Fr...

    百小僧5442021-12-06