C#中的泛型继承?

C#中的泛型继承?,c#,generics,inheritance,C#,Generics,Inheritance,可能重复: 我能行 public class MyGenericClass : DL //but i cannot do public class MyGenericClass <T> : T 公共类MyGenericClass:DL //但我做不到 公共类MyGenericClass:T 第二步我该怎么做?如果我做不到,我怎么能做这样的事情呢 public class MyGenericClass <T> { T obj; //have all

可能重复:

我能行

public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
公共类MyGenericClass:DL
//但我做不到
公共类MyGenericClass:T
第二步我该怎么做?如果我做不到,我怎么能做这样的事情呢

public class MyGenericClass <T> 
{
    T obj;
    //have all MyGenericClass.XYZ call obj.XYZ
}
public interface IXyzable { void xyz(); }

public class MyGenericClass<T> : IXyzable where T : IXyzable {
    T obj;
    public void xyz() {
        obj.xyz();
    }
}
公共类MyGenericClass
{
T-obj;
//让所有MyGenericClass.XYZ调用obj.XYZ
}

这是不可能的,因为根据T的类型,MyGenericClass的公共接口会发生变化


如果有许多不同的类都公开同一个接口,那么可以声明MyGenericClass来公开该接口,并且在所有函数的实现中,将调用委托给obj

public class MyGenericClass <T> 
{
    T obj;
    //have all MyGenericClass.XYZ call obj.XYZ
}
public interface IXyzable { void xyz(); }

public class MyGenericClass<T> : IXyzable where T : IXyzable {
    T obj;
    public void xyz() {
        obj.xyz();
    }
}
公共接口IXyzable{void xyz();}
公共类MyGenericClass:IXyzable其中T:IXyzable{
T-obj;
公共void xyz(){
obj.xyz();
}
}

编辑:现在我理解了这个问题

您将需要所有可能的T来实现一些接口,以便您知道obj.XYZ()是有意义的,然后您就可以这样做了

public interface Ixyz
{
    void XYZ();
}

public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
    T obj;

    public MyGenericClass()
    {
        obj = new T();
    }

    public void XYZ()
    {
        obj.XYZ();
    }
}
公共接口Ixyz
{
void XYZ();
}
公共类MyGenericClass:Ixyz,其中T:Ixyz,new()
{
T-obj;
公共MyGenericClass()
{
obj=新的T();
}
公共void XYZ()
{
obj.XYZ();
}
}
我也让MyGenericClass实现了Ixyz,因为它显然公开了正确的方法,但这可能是最好的选择,因为它允许

var x = new MyGenericClass<MyGenericClass<SomeClass>>();
var x=新的MyGenericClass();

这不太可能是一个好主意。

这几乎是duck类型,但您可以使用反射。 当您使用对obj的引用创建泛型类时,请使用反射来尝试找到具有正确签名的方法。只要存储对该方法的引用,性能就不会太差

class BaseGeneric<T>
{
    private T obj;
    private MethodInfo mi;
    private const string MethodNameOfInterest = "Xyz";

    public BaseGeneric(T theObject)
    {
        this.obj = theObject;
        Type t = obj.GetType();
         mi = t.GetMethod(MethodNameOfInterest);
    }

    public void Xyz()
    {
        mi.Invoke(obj, null);
    }
}   
classbasegeneric
{
私人T obj;
私有方法信息mi;
private const string MethodNameOfInterest=“Xyz”;
公共基泛型(T对象)
{
this.obj=对象;
类型t=obj.GetType();
mi=t.GetMethod(MethodNameOfInterest);
}
公共void Xyz()
{
mi.Invoke(obj,null);
}
}   

当然,您需要为错误检查等添加更多内容,但这就是您可以做的要点。另外,不要忘记将System.Reflection命名空间添加到using子句。

类型系统将不允许您尝试的表单的类型声明。不允许这样做的一个原因应该是直观的:当
T
是密封类(例如
System.String
)时,
MyGenericClass
将如何操作


如果您确实需要此功能(并且您知道将要使用的类型
T
未密封),则可以在运行时使用
Reflection.Emit
命名空间中的类生成代理。使用诸如PostSharp之类的AOP工具也可以达到这种效果。

具体问题是,为什么不能这样做:

public class MyGenericClass<T> : T
但是对于继承版本,这个技巧不起作用

此外,许多有用的设施不可能通过接口约束来描述。当您从类型继承时,您可以做的不仅仅是对其调用方法,还可以重写它们。考虑这个假设的例子:

class MyBase 
{
    public virtual void MyVirtual() { }
}

class MyGenericDerived<T> : T
{
    public override void MyVirtual() 
    {
        Console.WriteLine("Overridden!"); 
    }
} 

MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
类MyBase
{
公共虚拟空间MyVirtual(){}
}
类MyGenericDerived:T
{
公共覆盖无效MyVirtual()
{
Console.WriteLine(“重写!”);
}
} 
MyBase obj=新的MyGenericDerived();
obj.MyVirtual();
我想做的是类似于“mix-in”的事情,其中MyGenericDevertive提供了虚拟函数的定义,无论它应用于什么基础。但是编译器如何知道T将有一个名为MyVirtual的方法可以被重写呢?我需要在T上加一个约束。我如何通过接口来表达它?这是不可能的。一旦允许从类型参数继承,使用接口来描述约束就不是一个合适的解决方案。这就是为什么它在今天的语言中不存在的另一个原因。

这是怎么回事:

class BaseClass<T>
{
    public T property { get; set; }
}

class GenericClass<T> : BaseClass<T>
{ 

}

class Program
{
    static void Main(string[] args)
    {
        GenericClass<int> l = new GenericClass<int>();
        l.property = 10;
    }
}
类基类
{
公共T属性{get;set;}
}
类GenericClass:基类
{ 
}
班级计划
{
静态void Main(字符串[]参数)
{
GenericClass l=新的GenericClass();
l、 财产=10;
}
}

这实现了您想要做的事情?

为什么要投反对票?我回答了这个问题,不是吗?我不建议这样做,但它确实解决了他的问题:BaseGeneric.Xyz()调用底层对象的Xyz()方法,而不管该方法是什么类型。您的解决方案具有反射的所有缺点,并且没有duck类型的好处。外部对象(BaseGeneric)上必须声明所有函数。如果您知道这些函数,只需调用相同的函数即可?它缓存MethodInfo,因此性能损失会降低。它看起来像底层对象,所以它会嘎嘎作响。这确实让他重新实现了每种方法,所以这是最大的缺点。但是,T可以是实现Xyz的任何东西,在某些场景中很方便。如果您让他手动实现该方法,那么为什么不直接调用实现方法呢?为什么要使用反射呢?那是向下的声音的来源是的,你是对的。我感谢你的解释。我的方法唯一的优点是T可以是任何具有方法Xyz的类。如果无法访问代码且无法使用接口,则此操作非常方便。使用非常有限,但与C#4.0中即将出现的动态类型类似。您尝试这样做的动机是什么?等待C#4.0中的动态类型。但在第二种情况下,T用于声明成员,该成员可能是公共的,然后MyGenericClass的公共接口将根据T的类型而改变。只是属性的数据类型,它本质上由.net和泛型处理。我的观点更倾向于t