我有以下界面:
public interface IObject
{
double x { get; }
double y { get; }
Holder<IObject> Holder { get; set; }
}
和这个班级
public class Holder<T> where T : IObject
{
private List<T> items;
public void AddItem(T item){
items.Add(item);
item.Holder = this;
}
但是编译器不喜欢AddItem方法并且在这一行:
item.Holder = this;
给了我这个错误:
Cannot convert source type 'Holder<T>' to target type 'Holder<IObject>'
为什么我不能这样做,这个场景有什么好的解决方案? 谢谢
答案 0 :(得分:1)
如果可以转换那将是类型系统漏洞:
public class Holder<T> where T : IObject
{
public T SomeField;
}
...
var holder = new Holder<IObjectSubType2>();
Holder<IObject> dummy = holder; //assuming that this works
dummy.SomeField = new IObjectSubType1(); //violates type safety
IObjectSubType2 converted = holder.SomeField;
如您所见,我能够将IObjectSubType1
的实例转换为IObjectSubType2
。
这就是为什么不进行类型检查。
答案 1 :(得分:1)
你必须牢记Genrics在C#中的工作方式,编译器会创建一个指定类型的类,因此你就会有错误。
要解释更多,请参考以下示例:
public class InterfaceImplementation : IObject
{
}
然后你做的一些事情:
var genericInitialisation = new Holder<InterfaceImplementation>();
编译时编译器将创建一个类HolderInterfaceImplementation
,替换T
泛型参数的所有准确性。
所以在编译之后你将拥有这个课程:
public class HolderInterfaceImplementation
{
private ListInterfaceImplementation items;
public void AddItem(InterfaceImplementation item){
items.Add(item);
item.Holder = this;
}
并且item.Holder
将是HolderIObject
类型,因此编译器会报告有关无法将HolderInterfaceImplementation
转换为HolderIObject
的错误,这是合乎逻辑的。
在解释理论之后,解决方案自然而然,这是一个例子:
public interface IObject<T> where T : IObject<T>
{
double x { get; }
double y { get; }
Holder<T> Holder { get; set; }
}
public class Holder<T> where T : IObject<T>
{
public Holder()
{
items = new List<T>();
}
private List<T> items;
public void AddItem(T item)
{
items.Add(item);
item.Holder = this;
}
}
public class Implementation : IObject<Implementation>
{
public double x
{
get { return 0; }
}
public double y
{
get { return 0; }
}
public Holder<Implementation> Holder
{
get;
set;
}
}
static void Main(string[] args)
{
var t = new Holder<Implementation>();
t.AddItem(new Implementation());
Console.ReadKey();
}