C# 分配类型为T的数据成员字段/属性变量

C# 分配类型为T的数据成员字段/属性变量,c#,C#,为什么赋值语句 _t = new Y(); 导致以下编译器错误 无法将类型“Y”隐式转换为“T”。存在显式转换(是否缺少强制转换?) 公共类X{} 公共类Y{} 公共A类{} 公共类B:A,其中T:Y,new() { 私人电讯;; 公共图书馆B() { _t=新的t(); _t=new Y();//编译器错误 } } T x=(T)new Y()是显式转换。当且仅当T实际上是Y时,它才会在运行时工作。如果T是Y的任何子类,它将抛出异常。所以永远不要使用泛型类型参数——如果您的类要求t实际上总是

为什么赋值语句

_t = new Y();
导致以下编译器错误

无法将类型“Y”隐式转换为“T”。存在显式转换(是否缺少强制转换?)

公共类X{}
公共类Y{}
公共A类{}
公共类B:A,其中T:Y,new()
{
私人电讯;;
公共图书馆B()
{
_t=新的t();
_t=new Y();//编译器错误
}
}
T x=(T)new Y()是显式转换。当且仅当
T
实际上是
Y
时,它才会在运行时工作。如果
T
Y
的任何子类,它将抛出异常。所以永远不要使用泛型类型参数——如果您的类要求
t
实际上总是
Y
,那么它不应该是泛型的。它应该只使用
Y

T
是一个类型参数。只有一个允许值的参数不是参数。这是一个常数

public class Y
{
    public int YStuff;
}

public class YSubclass : Y
{
    public int YSubclassStuff;
}

public class Generic<T> where T : Y, new() {
    public static void Test() {
        //  NEVER DO THIS, EVER
        T x = (T)new Y();
    }
}
Y
没有该字段。您不能假装
Y
YSubclass
。事实并非如此。这不仅仅是“坏形式”或“捷径”之类的东西;这是不可能的

publicstaticvoidmain()
{
//嗯
Generic.Test();
//System.InvalidCastException:'无法强制转换类型为的对象
//“WpfApp1.Y”以键入“WpfApp1.YSubclass”
//这就是为什么我在Test()中所做的是一个非常非常糟糕的主意
//你永远不应该这样做。
Generic.Test();
}
您需要使用虚拟方法或接口来解决问题。这些是从这里到达那里的安全、可接受的方式

您可以要求T实现给定的接口,例如:

public interface Z
{
    void F();
}

public class Generic<T> where T : Y, Z, new()
公共接口Z
{
无效F();
}
公共类泛型,其中T:Y,Z,new()

现在,您可以创建一个
T
,不管它是什么,并保证任何
T
都具有
F()

编译器错误本身确切地告诉您为什么…T是Y的子类。您可以将T指定给Y的引用,因为作为Y的子类,T是Y,但不是相反。T是Y的超集。它是Y的全部,还有更多。Y没有“更多”。它不是T。更简单地说,你只是试着把
动物
放在声明为
@SamusArin的变量中,
T
可以是从
Y
派生的任何类型。它可以是Y本身,也可以是任何潜在存在的(或将来存在的)子类fromy(即,
公共类subclass fromy:Y{}
)。现在,您不能执行
子类fromy\u t=newy(),或者你可以吗?因此编译器抱怨…@SamusArin它说它不能隐式转换它。它还询问您是否打算显式转换它。你没有。这是一个常见的问题,因此提示,但在您的情况下,显式转换也不会成功,即使存在一个。在您的代码中,除非您知道一些关于未显示的类型的信息,否则无法对其进行转换。这样做是错误的。如果您要编写代码,使泛型方法在任何时候都失败,
T
不是
Y
,那么该方法就不应该是泛型的。@Servy我没说这是个好主意。但也许我应该明确地说这是一个糟糕透顶的想法。@EdPlunkett注意到Samus的回答正是这是一个糟糕答案的原因,你只是鼓励OP实际使用它。@Servy(和Ed)如果我在约束列表中列出我需要的三种特定类型,会怎么样?他们目前正在实现接口,但定义接口是为了查看和分析。我现在需要读/写DAL。我可以定义他们可以实现的另一个接口,或者看看是否可以修改现有的接口。最初的接口也有点像黑客b/c,无法进行多重继承,三个类中有一个已经有了父类(它们都是“附件”)类、AttachmentX、AttachmentY和AttachmentZ。AttachmentX:BaseRecord,因此我无法制作BaseAttachment。@SamusArin每次运行时使程序崩溃不是“快速修复”.这只是假装你没有问题,而你仍然有完全相同的问题,除非你现在没有意识到你仍然有完全相同的问题。
Y y = new Y();
var x = y.YSubclassStuff;
public static void Main()
{
    //  OK
    Generic<Y>.Test();

    //  System.InvalidCastException: 'Unable to cast object of type 
    //  'WpfApp1.Y' to type 'WpfApp1.YSubclass'.'
    //  And that's why what I did in Test() is a really, really bad idea
    //  and you should never do it. 
    Generic<YSubclass>.Test();
}
public interface Z
{
    void F();
}

public class Generic<T> where T : Y, Z, new()