C#generics约束传播

Mat*_*teS 5 c# generics

这个例子是对真正问题的简化,但我怎样才能编译它呢?我希望泛型约束能够传播.

由于T是TClass而TClass是一个类,为什么不是T类?

public class MyClass<TClass> where TClass : class 
{
    public void FuncA<Ta>() where Ta : class
    {
    }

    public void FuncB<Tb>() where Tb : TClass
    {
    }

    public void Func<T>()
        where T : TClass
    {
        FuncA<T>();
        FuncB<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

这实际上有效.Eric Lippert让我思考,谢谢.

由于T是TClass而TClass是TAnotherType,因此T实际上是TAnotherType.

public class MyClass<TClass, TAnotherType> where TClass : TAnotherType
{
    public void FuncA<Ta>() where Ta : TClass
    {
    }

    public void FuncB<Tb>() where Tb : TAnotherType
    {
    }

    public void Func<T>()
        where T : TClass
    {
        FuncA<T>();
        FuncB<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 14

既然TTClassTClass一个班级,为什么不是T一个班级?

前提1:"Bob Smith"是一个正确的名称.

前提2:"专有名称"是三个单词的句子片段.

结论:因此"Bob Smith"是一个三字句子片段.

这种逻辑显然不正确.

前提1:T是一个TClass

前提2:TClass是一个班级

结论:因此T是一个阶级.

出于同样的原因,这种逻辑是不正确的.

在这两种情况下,我们使用"是"来表示两个前提中的两个完全不同的东西.在第一个前提中,"是"用于表示"这两个事物之间存在着一种关系".在第二个前提中,"是"用于表示"这一件事具有特定的特征".

您可以通过简单地替换for T和来看到您的逻辑更直接错误TClass:

前提1:int是一个System.ValueType

('是'表示'具有子类关系')

前提2:System.ValueType是一个班级

('是'表示'具有特定属性,即通过引用复制)

结论:因此int是一个阶级.

而且,我们得出一个不正确的结论,因为"is"以两种不一致的方式使用.

另一个例子:

前提1:汉堡包总比没有好.

前提2:没有比一块好牛排更好的了.

结论:通过传递性,汉堡比优质牛排更好.

最后,有关此主题的更多想法,请参阅我最近的文章:

http://ericlippert.com/2011/09/19/inheritance-and-representation/

  • @Rob:我做了**给出一个不是这样的例子.再次阅读答案.为什么您认为从引用类型派生的类型必须是引用类型?继承共享*成员*.其他属性不是继承的.鸭嘴兽是动物,动物是六个字母的单词,因此鸭嘴兽是六个字母的单词?我不这么认为. (3认同)
  • 如果这是一个很好的汉堡包可能会.与厨师交朋友,你会对汉堡包的好吃感到惊讶!:) (2认同)

Jon*_*eet 6

问题是T不必是引用类型.考虑:

MyClass<IFormattable> foo = new MyClass<IFormattable>();
MyClass.Func<int>();
Run Code Online (Sandbox Code Playgroud)

这会尝试调用,FuncA<int>int不遵守: class约束.

所以基本上你需要添加: class约束Func<T>:

public void Func<T>() where T : class, TClass
Run Code Online (Sandbox Code Playgroud)


Sae*_*iri 4

为了编译这个,请执行以下操作:

public void Func<T>()
    where T :class, TClass
{
    FuncA<T>();
    FuncB<T>();
}
Run Code Online (Sandbox Code Playgroud)

因为FunA的输入只是一个类而不是特殊类。