C#中的泛型继承?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/748706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:40:08  来源:igfitidea点击:

generic inheritance in C#?

c#genericsinheritance

提问by

Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?

可能的重复:
为什么 C# 泛型不能像在 C++ 模板中那样从泛型类型参数之一派生?

I can do

我可以

public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T

How would i do the second? if i cannot do that, how can i do something like

我该怎么做第二个?如果我不能这样做,我该怎么做

public class MyGenericClass <T> 
{
    T obj;
    //have all MyGenericClass.XYZ call obj.XYZ
}

回答by Jason Coyne

This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.

这是不可能的,因为根据 T 是什么类型,MyGenericClass 的公共接口会改变。

If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj

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

回答by erikkallen

You could do something like

你可以做类似的事情

public interface IXyzable { void xyz(); }

public class MyGenericClass<T> : IXyzable where T : IXyzable {
    T obj;
    public void xyz() {
        obj.xyz();
    }
}

Edit: Now I understand the question

编辑:现在我明白了这个问题

回答by stevemegson

You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do

您将需要所有可能的 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();
    }
}

I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows

我也让 MyGenericClass 实现了 Ixyz,因为它显然确实公开了正确的方法,但也许最好将其排除,因为它允许

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

which is unlikely to ever be a good idea.

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

回答by Erich Mirabal

This is pretty much duck-typing, but you could use reflection. When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.

这几乎是鸭子类型,但您可以使用反射。当您使用对 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);
    }
}   

Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.

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

回答by kvb

The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T>act when Tis a sealed class (e.g. System.String)?

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

If you absolutely need this functionality (and you know that the type Tyou'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emitnamespace. It may also be possible to achieve this effect using AOP tools like PostSharp.

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

回答by Daniel Earwicker

The specific question, why can't you do this:

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

public class MyGenericClass<T> : T

And you can do this:

你可以这样做:

public class MyGenericClass<T> 
{
   T obj;
}

The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.

原因是 CLR 喜欢能够为 MyGenericClass 编译单个版本的代码,该版本适用于为 T 指定的任何引用类型。

It can do this for the second case, because it can quietly replace Twith objectand insert appropriate casts, roughly equivalent to:

它可以为第二种情况下做到这一点,因为它可以悄悄地更换Tobject和插入适当的铸件,大约相当于:

public class MyGenericClass 
{
   object obj;
}

But for the inheritance version, that trick doesn't work.

但是对于继承版本,这个技巧不起作用。

Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:

此外,许多有用的设施将无法通过接口约束来描述。当你从一个类型继承时,你可以做的不仅仅是调用它的方法——你也可以覆盖它们。考虑这个假设的例子:

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

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

MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();

What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.

我想要做的是类似于“混入”的事情,其中​​ MyGenericDerived 在任何基础上为虚函数提供定义。但是编译器怎么知道 T 会有一个叫做 MyVirtual 的方法可以被覆盖呢?我需要对 T 施加约束。我将如何通过接口表达它?不可能。一旦允许从类型参数继承,使用接口来描述约束就不是一个合适的解决方案。所以这就是为什么它在今天的语言中不存在的另一个原因。

回答by MRFerocius

What about this:

那这个呢:

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;
    }
}

This achieves what you want to do?

这实现了你想要做什么?