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:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...
随机推荐
- word设置每页50行
1. 显示行号:页面布局-行号-每页重编行号 2. 调整页边距:页面布局-页边距-调整上下边距为2 3. 调整行数:页面布局-文档网格-只指定网格-设置行数
- ubuntu16.04 python3 安装selenium及环境配置
环境 ubuntu16.04 python3 安装selenium sudo pip3 install seleium 默认安装完是支持firefox,但是更新得太慢对于较新的firefox已经不支持 ...
- RMI远程服务调用
数据库:info.sql /* Navicat MySQL Data Transfer Source Server : yuanzhen Source Server Version : 50713 S ...
- Batch Normalization&Dropout浅析
一. Batch Normalization 对于深度神经网络,训练起来有时很难拟合,可以使用更先进的优化算法,例如:SGD+momentum.RMSProp.Adam等算法.另一种策略则是高改变网络 ...
- qt pro 设置编译参数,支持 xp
#兼容 XP VS2015 5.01 版本 win32 { QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01 QMAKE_LFLAGS_CONSOLE = ...
- LOJ6000 - 「网络流 24 题」搭配飞行员
原题链接 题意简述 求二分图的最大匹配. 题解 这里写的是匈牙利算法. 表示节点的当前匹配. 为真表示在这一轮匹配中,无法给节点一个新的匹配.所以如果为真就不用再dfs它了,直接continue就好. ...
- Python+Selenium基础篇之1-环境搭建
Python + Selenium 自动化环境搭建过程 1. 所需组建 1.1 Selenium for python 1.2 Python 1.3 Notepad++ 作为刚初学者,这里不建议使用P ...
- windows系统php配置redis
网上各种找教程各种不行,最后东拼西凑的终于把redis弄出来了. PHP版本:7.1.0: Redis版本:3.2.10: Windows版本:Windows7: 一.Windows下安装Redis ...
- 【其他】Objective-C 内存管理学习总结
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/OC_CG.html 最近学习了Objective-C语言(以下简称OC),其他的都还好,唯有它的内存管理让我不知所 ...
- caffe+GAN︱PPGN生成模型5则官方案例(caffe版)
一.效果与架构 PPGN 整合了对抗训练.cnn特征匹配.降噪自编码.Langevin采样:在NIPS2016得到了Ian Goodfellow的介绍. PPGN生成的图像同类差异化大,可根据指定生成 ...