任何人都可以解释为什么在下面调用'DoTest1'方法是个问题?
至于为什么我需要将传入的GridCore对象仍然转换为泛型类型T,即使我指定T派生自GridCore,其中我的位置为T:GridCore?
由于
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
MyTest<MyAlbum> mytest = new MyTest<MyAlbum>();
mytest.DoTest1(new MyAlbum());
mytest.DoTest2(new MyAlbum());
}
}
public class GridCore { }
public class MyAlbum : GridCore
{
public string Title { get; set; }
}
public class MyTest<T> where T : GridCore
{
private List<T> _list = new List<T>();
public void DoTest1(GridCore ma)
{
//_list.Add(ma); <-- why doesn't this work?
_list.Add((T)ma);
}
public void DoTest2(T ma)
{
_list.Add(ma);
}
}
答案 0 :(得分:2)
如果您希望自己的方法推断GridCore
是T
(因为约束),那么在编译时它不能。这就是你得到错误的原因。
Generic Methods (C# Programming Guide)
编译器可以根据方法推断类型参数 你传递的论据;它无法仅从中推断出类型参数 约束或返回值。
答案 1 :(得分:0)
private List<T> _list = new List<T>();
_list是T型,而ma
public void DoTest1(GridCore ma)
是GridCore类型。这就是为什么它不起作用。
答案 2 :(得分:0)
C#确实要求开发人员将对象显式地转换为其任何派生类型,因为这样的转换可能会在运行时失败。 T来自GridCore。所以你可以写
GridCore gridcore = new T();
但应在
中明确转换T t = (T)new GridCore();
答案 3 :(得分:0)
where T: GridCore
表示T
是GridCore
,即GridCore
是T
的基本类型或界面。
但您的列表是List<T>
,也就是说,它是T
和T
的列表,可能是GridCore
的派生类。
我们假设T
是DerivedGridCore
并且有一个字段int X
,那么GridCore
应该有一个字段int X
?
除非你明确地转换类型(或者有一个隐式运算符),否则编译器不会做出这个假设,因为转换不能保证。
为了更直观地思考,Girafe
是Animal
,但Animal
不一定只能是Girafe
; Tirget
是Animal
。
答案 4 :(得分:0)
简而言之,因为并非所有GridCore
都是T
。所有T
都是GridCores
(因为约束),而不是相反。
想象一下:
public class MyChicken : GridCore
{
public string FavouriteColour { get; set; }
}
....
new MyTest<MyAlbum>().DoTest1(new MyChicken());
如果您的代码被允许,那么当您期待专辑时,您现在就会有一只鸡。毋庸置疑,试图听音乐的人可能无法达到他们的期望。
您可能想要的是将DoTest1
签名更改为仅接受该类处理的T
:
public void DoTest1(T ma)
现在,MyTest<MyAlbum>
只会接受MyAlbum
方法的DoTest1
。