考虑以下代码:
public class Person
{
public string Name { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
public interface IHandler<T>
{
T Handle(T eventData);
}
public class UpdatePersonHandler : IHandler<Person>
{
public Person Handle(Person eventData)
{
var test = eventData.Name;
return eventData;
}
}
public class UpdatePersonHandler2 : IHandler<Person>
{
public Person Handle(Person eventData)
{
var test = eventData.Name;
return eventData;
}
}
public class UpdateAnimalHandler : IHandler<Animal>
{
public Animal Handle(Animal eventData)
{
var test = eventData.Name;
return eventData;
}
}
public class Bus<T>
{
public static readonly IList<IHandler<T>> Handlers = new List<IHandler<T>>();
public static void Register(IHandler<T> handler)
{
if (handler != null)
Handlers.Add(handler);
}
public static void Raise(T eventData)
{
foreach (var handler in Handlers)
{
handler.Handle(eventData);
}
}
}
和这个测试代码:
[TestMethod]
public void TestRegister()
{
Bus<Person>.Register(new UpdatePersonHandler());
Bus<Person>.Register(new UpdatePersonHandler());
Bus<Person>.Register(new UpdatePersonHandler2());
Bus<Animal>.Register(new UpdateAnimalHandler());
Debug.Print(Bus<Person>.Handlers.Count.ToString());
Debug.Print(Bus<Animal>.Handlers.Count.ToString());
}
此测试的输出是:
3
1
这里发生了什么?
看起来框架正在为通过static
Register方法呈现给它的每种类型新建一个Bus类。为此,它必须为Bus<T>
调用每个新类型的默认构造函数。
但为什么呢?这是如何工作的?
这是否有任何实际用途,或者它只是一个有趣但模糊的C#好奇心,应该在生产代码中避免?
答案 0 :(得分:3)
是的,传递给静态类Bus<T>
的每个不同类型都会导致调用默认构造函数。验证这一点的简单方法是给它一个默认的构造函数:
static Bus(){ Debug.Print("ctor"); }
使用它会产生输出
ctor
ctor
3
1
这样做的原因是泛型类只是类的模板,静态类仍然如此。一旦为Bus
类提供了泛型类型,那么模板将被实现为类,即调用构造函数时。
此物化类对于同一类的其他泛型类型是唯一的。因此,当使用Bus<Person>
和Bus<Animal>
时,它们实际上是单独的类,具有单独的静态成员数据,并且需要单独的实例化。
关于通用类型的静态字段的使用和展望,有一个MSDN警告(显然Resharper会选择这个)
CA1000:不要在泛型类型上声明静态成员
https://msdn.microsoft.com/en-us/library/ms182139(VS.80).aspx