4

谁能解释一下为什么调用下面的“DoTest1”方法是一个问题?

至于为什么我需要将传入的 GridCore 对象仍然转换为泛型类型 T 即使我指定 T 派生自 GridCore 与我的 where 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);
    }

}
4

5 回答 5

2

如果您期望您的方法推断出这GridCoreT由于约束),那么在编译时它不能。这就是您收到错误的原因。

泛型方法(C# 编程指南)

编译器可以根据你传入的方法参数来推断类型参数;它不能仅从约束或返回值推断类型参数。

于 2013-03-28T08:59:53.853 回答
0
       private List<T> _list = new List<T>(); 

_list 是类型 T,而 ma

       public void DoTest1(GridCore ma)

是 GridCore 类型。这就是为什么它不起作用。

于 2013-03-28T08:57:36.073 回答
0

C# 确实要求开发人员将对象显式转换为它的任何派生类型,因为这样的转换可能在运行时失败。T 源自 GridCore。所以你可以写

GridCore gridcore = new T();

但应该明确输入

T t = (T)new GridCore();
于 2013-03-28T08:58:24.387 回答
0

where T: GridCore表示 aT是 a GridCore,即是GridCore的基类型或接口T

但是您的列表是List<T>,也就是说,它是 的列表,T并且T可能是 的派生类GridCore

让我们假设TisDerivedGridCore并且有一个字段int X,那么GridCore应该有一个字段int X吗?

除非您显式转换类型(或存在隐式运算符),否则编译器不会做出该假设,因为不能保证该转换。

对于更直观的思考,aGirafe是一个Animal,但 an Animalis 不一定只能是 a Girafe;aTirget要么是Animal.

于 2013-03-28T09:09:37.000 回答
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)

现在, aMyTest<MyAlbum>将只接受MyAlbum它的DoTest1方法。

于 2013-03-28T09:12:15.053 回答