我正在编写一种方法,该方法根据传入的类型为加载过程返回类的不同实例。
我要写的方法将像这样使用:
Loader<MyType> loader = context.GetLoader<MyType>();
loader.Load(myTypeArray);
在内部,我打算将加载器作为值保留Dictionary<Type, T>
。但是,我不确定T
应该是哪种类型。
我可以制作T
object
,但我更喜欢将其保留为Loader<>
。我知道我需要以任何一种方式进行转换,但是使用Loader<>
会带来更多类型安全性。
有什么好的方法可以实现吗?
答案 0 :(得分:3)
您有两种选择。两者都需要您添加接口。
添加一个普通的ILoader
(无类型参数)接口,并在您的加载程序中将其实现为class Loader<T> : ILoader
。通用界面可让您将所有加载程序存储在List<ILoader>
中。
interface ILoader {}
class Loader<T> : ILoader {}
void Example()
{
var loaders = new List<ILoader>();
loaders.Add( new Loader<Foo>() );
loaders.Add( new Loader<Bar>() );
}
定义一个新的协变接口ILoader<out T>
,并在您的Loader中将其实现为class Loader<T> : ILoader<T>
。协方差将允许您将所有加载程序存储在List<ILoader<object>>
中。此选项仅在T
是引用类型时才有效,并且仅在您的接口方法都没有接受T
作为参数时才可行。
interface ILoader<out T>
{
//void SetLoader(T input); //Does not compile due to covariance
T GetLoader(); //Read is allowed
}
class Loader<T> : ILoader<T>
{
public void SetLoader(T input) {} //Works when not in interface
public T GetLoader() { return default(T); }
}
void Example()
{
var loaders = new List<ILoader<object>>();
loaders.Add( new Loader<Foo>() );
loaders.Add( new Loader<Bar>() );
}
答案 1 :(得分:2)
我可以制作
T
object
,但我更喜欢将其保留为Loader<>
。我知道我需要以任何一种方式进行转换,但是使用Loader<>
会带来更多类型安全性。
不,它不会;这句话自相矛盾!您说“我知道我需要强制转换”,所以已经有零编译时类型安全性,并且您可以获得更多类型安全性,但是零是不超过零!
请记住,保留表示形式的强制转换的功能恰恰是“我知道编译器在编译时不知道的在运行时将是正确的事实”。 那是演员的目的。
在C#类型系统中无法表示“这是C<?>
类型的事物”,因此不要尝试查找它。您已经接受了运行时类型检查,因此继续吧。您的变量dict[typeof(T)]
产生的类型为Loader<T>
不变。唯一可以保持不变的人是 you ,因此,甚至不要试图依靠编译器为您做到这一点。