C#:继承过程中的静态成员
在知乎上看到一个关于“泛基“的实现,感觉挺有意思,想试试效果,代码如下:
public abstract class MyBase<T> where T : MyBase<T>
{
public static string DataForThisType { get; set; }
public static T Instance { get; protected set; }
public static readonly IReadOnlyDictionary<string, MemberInfo> Members = typeof(T).GetMembers().ToDictionary(x => x.Name);
} public class MyClass : MyBase<MyClass>
{
static MyClass()
{
DataForThisType = string.Format("MyClass got {0} members", Members.Count);
Instance = new MyClass();
}
}
class Program
{
static void Main(string[] args)
{
Console.Write(MyClass.DataForThisType);
Console.WriteLine();
Console.ReadLine();
}
}
先忽略这段代码的作用,重点是运行后控制台没有任何输出。跟踪一下发现根本没有走MyClass(),DataForThisType的值一直是null。关于静态构造方法,网上的解释是:
- 通常情况下:最先调用基类的构造方法,但如果该类有静态构造方法,且首次调用该类,则先调用该类的静态构造方法,再调用其基类的静态构造方法。
Child.Static->Super.Static->Super.Instance->Child Instance - 静态构造方法是.net调用的,在创建第一个实例或者静态成员被引用时,.net将自动调用静态构造方法来初始化类。
这就有问题了,MyClass的静态构造方法不仅没被优先调用,甚至全程都没有被调用。难道上述这个说法是错的?为了排除干扰,给上述代码简化一下
class Program
{
static void Main(string[] args)
{
Console.Write(TestChild.StaticPropertyBase);
Console.WriteLine();
Console.ReadLine();
}
} public class TestBase
{
public static string StaticPropertyBase { get; protected set; }
} public class TestChild : TestBase
{
static TestChild()
{
StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase";
}
}
运行结果还是一样,没有输出,TestChild的静态构造没被执行。回头再来看静态构造方法的调用条件:在创建第一个实例或者静态成员被引用时!!!实例是肯定没有的,但
是我有引用静态成员啊..等等,我引用的好像是父类的静态成员,难道父类的静态成员不行?说好的继承全部家产呢?那就再来试试,给TestChild声明一个自己的静态属性。
class Program
{
static void Main(string[] args)
{
Console.Write(TestChild.StaticPropertyChild);
Console.WriteLine();
Console.Write(TestChild.StaticPropertyBase);
Console.WriteLine();
Console.Write(TestBase.StaticPropertyBase);
Console.WriteLine();
Console.ReadLine();
}
} public class TestBase
{
public static string StaticPropertyBase { get; protected set; }
} public class TestChild : TestBase
{
public static string StaticPropertyChild { get; set; }
static TestChild()
{
StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase";
StaticPropertyChild = "StaticPropertyChild";
}
}
输出如下:
目前为止可以得出两个结论:
1)想触发一个类的静态构造方法?要么实例化它,要么访问它的静态成员,访问它基类的的静态成员是不行的。
2)静态成员的继承其实并不是真正的继承,或者说根本就无法继承,只是访问父类的静态成员而已。但与实例成员不同的是,用protected修饰的静态成员
可以在其派生类中访问,用protected修饰的非静态成员,则不可访问。下面代码体会一下,new TestBase().hh =" ";这句报错。
报错的原因描述有误:实则是因为在一个实例中访问了另一个实例的protected成员,与是否是基类的实例无关
public class TestBase
{ public static string StaticPropertyBase { get; protected set; }
public string hh { get; protected set; }
} public class TestChild : TestBase
{
public static string StaticPropertyChild { get; set; } static TestChild()
{
StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase";
StaticPropertyChild = "StaticPropertyChild";
}
TestChild()
{
hh = "";
new TestBase().hh = "";
}
}
以上、欢迎交流指正。如有侵权,请联系作者删除。
C#:继承过程中的静态成员的更多相关文章
- Java:验证在类继承过程中equals()、 hashcode()、toString()方法的使用
以下通过实际例子对类创建过程汇中常用的equals().hashcode().toString()方法进行展示,三个方法的创建过程具有通用性,在项目中可直接改写. //通过超类Employee和其子类 ...
- 继承过程中对函数中this的认识
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python说文解字_继承过程中的参数集合
1. 先看一段属性继承的代码: class User: def __init__(self,name,age): self.name = name self.age = age class User1 ...
- 编写高质量代码改善C#程序的157个建议[优先考虑泛型、避免在泛型中声明静态成员、为泛型参数设定约束]
前言 泛型并不是C#语言一开始就带有的特性,而是在FCL2.0之后实现的新功能.基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用.同时,它减少了泛型类及泛型方法中的转型,确保了类型安全.委托 ...
- Java类继承关系中的初始化顺序
Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...
- MySQL Fabric和MyBatis的整合过程中遇到的问题
这是我昨天在整合MySQL Fabric和MyBatis时遇到的问题,花了大半天才解决的问题,解决的过程中在网上查找了很久,都没有找到解决的方案.现在记下来,希望能够帮助有同样问题的朋友.如果各位朋友 ...
- 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧
[源码下载] 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 作者:webabcd 介绍背水一战 Wind ...
- 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧
背水一战 Windows 10 之 绑定 x:Bind 绑定 x:Bind 绑定之 x:Phase 使用绑定过程中的一些技巧 示例1.演示 x:Bind 绑定的相关知识点Bind/BindDemo.x ...
- java继承关系中成员变量,构造方法,成员方法的关系
Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...
随机推荐
- Java 面向对象三大特征之一: 多态
多态与类型转换 子类重写父类方法 1)位置:子类和父类中有同名的方法 2)方法名相同,返回类型和修饰符相同,参数列表相同 方法体不同 多态的优势和应用场合 多态:同一个引用类型,使用不同的 ...
- Yii2 Restful Api 401
采用Yii2 Restful Api方式为APP提供数据,默认你已经做好了所有的编码和配置工作.采用Postman测试接口: 出现这个画面的一个可能原因是:access_token的写法有误,如果你使 ...
- 深入研究Node.js的底层原理和高级使用
深入研究Node.js的底层原理和高级使用
- UVA - 1632 Alibaba 区间dp
题意:给定n个点,其中第i个点的坐标是,且它会在秒后消失.Alibaba可以从任意位置出发,求访问完所有点的最短时间.无解输出No solution. 思路:表示访问完区间后停留在i点的最短时间,表示 ...
- H3C无线路由器安装与设置
一.电脑与路由器的连接利用一根cat5e网线一头连接到电脑上笔记本或台式机都可以,另一头连接到无线路由器的LAN口任意LAN口都可以二.设置无线路由器完成路由器安装与电脑连接后,接下首次使用就需要设置 ...
- python网络编程基础知识整理
- (28000): Access denied for user 'root'@'127.0.0.1' (using password: YES)
在一台测试服务器测试Python脚本时,执行Python脚本时报如下错误: 主要错误信息为"operation the sql fail!1045 (28000): Access den ...
- zTree实现地市县三级级联报错(三)
zTree实现地市县三级级联报错(三) 1.具体报错如下 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] ...
- zTree实现多选树
zTree实现多选树 1.实现源码 <!DOCTYPE html> <html> <head> <title>多选树</title> < ...
- JavaScript获取地址栏中的参数
JavaScript获取地址栏中的参数 1.获取地址栏中的参数 (1)若地址栏中的地址是: http://10.124.36.56:8080/CMOD/index.jsp?name=you&p ...