(感谢大家的答案,这是我的重构示例,反过来另一个关于单一责任原则的StackOverflow问题.)
从PHP到C#,这种语法令人生畏:
container.RegisterType<Customer>("customer1");
Run Code Online (Sandbox Code Playgroud)
直到我意识到它表达了同样的事情:
container.RegisterType(typeof(Customer), "customer1");
Run Code Online (Sandbox Code Playgroud)
正如我在下面的代码中演示的那样.
那么为什么在这里使用泛型(例如整个Unity和大多数C#IoC容器)有一些原因,除了它只是一个更清晰的语法,即你在发送类型时不需要typeof()?
using System;
namespace TestGenericParameter
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
container.RegisterType<Customer>("test");
container.RegisterType(typeof(Customer), "test");
Console.ReadLine();
}
}
public class Container
{
public void RegisterType<T>(string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", typeof(T), dummy, typeof(T).Name);
}
public void RegisterType(Type T, string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", T, dummy, T.Name);
}
}
public class Customer {}
}
//OUTPUT:
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
Run Code Online (Sandbox Code Playgroud)
泛型非常有用的原因之一是当泛型类型参数用作参数类型或方法的返回类型时。这意味着,您可以编写类似的方法
public T GetAs<T>(string name)
Run Code Online (Sandbox Code Playgroud)
编译器可以检查返回类型,有时可以避免装箱值类型。调用者会写:
int value = GetAs<int>("foo");
Run Code Online (Sandbox Code Playgroud)
如果没有泛型,你将不得不写
public object GetAs(Type t, string name)
Run Code Online (Sandbox Code Playgroud)
并且调用者必须再次转换结果:
int value = (int)GetAs(typeof(int), "foo");
Run Code Online (Sandbox Code Playgroud)
主要原因是编译时的类型安全性.如果要传递两个Type对象,则将责任放在开发人员而不是编译器上.
这也是许多IoC容器利用它的原因,因为如果具体类型没有继承抽象类型,编译器会抱怨.
public void Register<TAbstract, TConcrete>() where TConcrete : TAbstract
{
}
Run Code Online (Sandbox Code Playgroud)
此代码仅在TConcrete实现或继承时才有效TAbstract.如果此方法采用两个Type参数,则您的方法应验证此关系.