gpt4 book ai didi

c# - 为什么通用类型约束不能继承/分层实现

转载 作者:太空宇宙 更新时间:2023-11-03 15:32:29 24 4
gpt4 key购买 nike

物品类别

public class Item
{
public bool Check(int value) { ... }
}


具有通用类型约束的基本抽象类

public abstract class ClassBase<TItem>
where TItem : Item
{
protected IList<TItem> items;

public ClassBase(IEnumerable<TItem> items)
{
this.items = items.ToList();
}

public abstract bool CheckAll(int value);
}


没有约束的继承类

public class MyClass<TItem> : ClassBase<TItem>
{
public override bool CheckAll(int value)
{
bool result = true;
foreach(TItem item in this.items)
{
if (!item.Check(value)) // this doesn't work
{
result = false;
break;
}
}
return result;
}
}


我想知道为什么泛型类型约束不能继承?因为如果我的继承类继承自基类并传递对其基类有约束的泛型,则它自动意味着继承类中的泛型应具有相同的约束,而无需显式定义。不是吗

我是在做错事,理解错了还是真的泛型类型约束不可继承?如果后者是正确的,那为什么呢?

一点额外的解释

为什么我认为应该在子类上继承或强制在类上定义的泛型类型约束?让我给您一些额外的代码,以使其不那么明显。

假设我们具有上述所有三个类。然后我们还有这个课:

public class DanteItem
{
public string ConvertHellLevel(int value) { ... }
}


如我们所见,该类不是从 Item继承的,因此不能用作 ClassBase<DanteItem>的具体类(忘记了 ClassBase现在是抽象的事实。它也可以是常规类) 。由于 MyClass没有为其泛型定义任何约束,因此具有 MyClass<DanteItem>似乎是完全有效的...

但。这就是为什么我认为泛型类型约束应该像继承成员泛型类型约束一样在继承的类上被继承/强制,因为如果我们查看 MyClass的定义,它说:

MyClass<T> : ClassBase<T>


TDanteItem时,我们可以看到它不能自动与 MyClass一起使用,因为它是从 ClassBase<T>继承的,并且 DanteItem不满足其通用类型约束。我可以说** MyClass上的通用类型取决于 ClassBase通用类型约束,因为否则 MyClass可以用任何类型实例化。但是我们知道不可能。

当我将 MyClass定义为时,当然会有所不同:

public class MyClass<T> : ClassBase<Item>


在这种情况下,T与基类的泛型没有任何关系,因此它与它无关。

这都是冗长的解释/原因。我可以简单地总结一下:


  如果我们不对 MyClass提供通用类型约束,则暗示我们可以使用任何具体类型实例化 MyClass。但是我们知道这是不可能的,因为 MyClass是从 ClassBase继承的,并且具有通用类型约束。


我希望现在这更有意义。

最佳答案

另一个更新:

这个问题是the subject of my blog in July 2013。感谢您提出的好问题!

更新:

我对此进行了更多思考,我认为问题是您根本不需要继承。相反,您想要的是对于必须放置在类型参数上的所有约束,以便将该类型参数用作另一种类型中的类型参数,以自动推导并以无形方式将其添加到类型参数的声明中。是?

一些简化的示例:

class B<T> where T:C {}
class D<U> : B<U> {}


U是在必须为C的上下文中使用的类型参数。因此,您认为编译器应推断出该类型并自动在U上施加C约束。

那这个呢?

class B<T, U> where T : X where U : Y {}
class D<V> : B<V, V> {}


现在,V是在必须同时为X和Y的上下文中使用的类型参数。因此,您认为编译器应推断出这一点,并自动对V施加X和Y的约束。是吗?

那这个呢?

class B<T> where T : C<T> {}
class C<U> : B<D<U>> where U : IY<C<U>> {}
class D<V> : C<B<V>> where V : IZ<V> {}


我只是弥补了这一点,但向您保证这是一个完全合法的类型层次结构。请描述一个清晰一致的规则,该规则不会进入无限循环以确定T,U和V上的所有约束是什么。不要忘记处理已知类型参数为引用类型且接口约束具有协方差或相反方差注释!而且,该算法必须具有以下特性:无论源代码中的B,C和D顺序是什么,它都给出完全相同的结果。

如果要使用约束推理,那么编译器必须能够处理这种情况,并在无法处理时给出明确的错误消息。

基本类型有什么特别之处?为什么不真正完全实现该功能?

class B<T> where T : X {}
class D<V> { B<V> bv; }


V是在必须可转换为X的上下文中使用的类型参数;因此,编译器应推断出这一事实,并对V施加X约束。是吗?或者没有?

为什么字段特别?那这个呢:

class B<T> { static public void M<U>(ref U u) where U : T {} }
class D<V> : B<int> { static V v; static public void Q() { M(ref v); } }


V是在只能为int的上下文中使用的类型参数。因此,C#编译器应推断出这一事实,并自动对V施加int约束。

是?没有?

你知道这是怎么回事吗?它在哪里停下来?为了正确实现所需的功能,编译器必须进行整个程序分析。

编译器不会进行此级别的分析,因为这会使工作陷入困境。构造泛型时,需要向编译器证明您已满足约束。弄清楚您的意思并弄清楚还有哪些约束集可以满足原始约束,不是编译器的工作。

出于类似的原因,编译器也不会尝试代表您自动推断接口中的差异注释。有关详细信息,请参见我关于该主题的文章。

http://blogs.msdn.com/b/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx



原始答案:


  我想知道为什么泛型类型约束不能继承?


仅成员被继承。约束不是成员。


  如果我的继承类从基类继承并传递对其基类有约束的泛型,则它自动意味着继承类中的泛型应具有相同的约束,而无需显式定义。不是吗


您只是在断言应该如何做,而没有提供为什么要那样做的任何解释。向我们解释为什么您认为世界应该是这种方式;好处是什么,缺点是什么,成本是多少?


  我是在做错事,理解错了还是真的泛型类型约束不可继承?


通用约束不被继承。


  如果后者是正确的,那为什么呢?


默认情况下,功能“未实现”。我们不必提供未实现功能的原因!除非有人花钱实施它,否则不会实现每个功能。

现在,我必须注意通用类型约束是在方法上继承的。方法是成员,成员是继承的,约束是方法的一部分(尽管不是其签名的一部分)。因此,约束在继承时会随方法一起出现。当你说:

class B<T> 
{
public virtual void M<U>() where U : T {}
}

class D<V> : B<IEnumerable<V>>
{
public override void M<U>() {}
}


然后 D<V>.M<U>继承约束并用 IEnumerable<V>代替T;因此,约束条件是U必须可转换为 IEnumerable<V>。请注意,C#不允许您重新声明约束。我认为这是一个错误的功能;我希望能够重新声明该约束以便清晰。

但是D不会从B继承对T的任何约束。我不知道怎么可能。 M是B的成员,由D及其约束继承。但是T首先不是B的成员,那么要继承什么呢?

我真的根本不了解您想要的功能是什么。您能否详细说明?

关于c# - 为什么通用类型约束不能继承/分层实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33297991/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com