抽象实现接口上的 C# 协方差

发布于 2024-11-24 17:49:20 字数 962 浏览 1 评论 0原文

使用 C#/.NET 4.0,我希望以下场景是可能的:

interface IA<out TB> where TB : IB { }
interface IB { }

class A<TB> : IA<TB> where TB : IB { }
class B : IB { }


abstract class AbstractA<TB> : IA<TB> where TB : IB { }
class DerivedA<TB> : AbstractA<TB> where TB : IB { }

static void Main(string[] args) {
    var myAB = new A<B>();
    Debug.Assert(myAB is IA<B>); // fine
    Debug.Assert(myAB is IA<IB>); // fine

    var myDerivedAB = new DerivedA<B>();
    Debug.Assert(myDerivedAB is IA<IB>); // fine
    Debug.Assert(myDerivedAB is DerivedA<B>); // fine
    Debug.Assert(myDerivedAB is DerivedA<IB>); // NOT fine        
}

遗憾的是,最后一个测试失败了,尽管类型显然是兼容的。除了测试每个已知的 IB 实现之外,是否还有另一种方法来测试这一点?

class FirstB : IB { }
class SecondB : IB { }
Debug.Assert(myDerivedAB is DerivedA<FirstB> || myDerivedAB is DerivedA<SecondB>) 

Using C#/.NET 4.0 I was hoping the following scenario would be possible:

interface IA<out TB> where TB : IB { }
interface IB { }

class A<TB> : IA<TB> where TB : IB { }
class B : IB { }


abstract class AbstractA<TB> : IA<TB> where TB : IB { }
class DerivedA<TB> : AbstractA<TB> where TB : IB { }

static void Main(string[] args) {
    var myAB = new A<B>();
    Debug.Assert(myAB is IA<B>); // fine
    Debug.Assert(myAB is IA<IB>); // fine

    var myDerivedAB = new DerivedA<B>();
    Debug.Assert(myDerivedAB is IA<IB>); // fine
    Debug.Assert(myDerivedAB is DerivedA<B>); // fine
    Debug.Assert(myDerivedAB is DerivedA<IB>); // NOT fine        
}

Sadly the last test fails, although the types clearly are compatible. Would there be another way to test this, other than testing for every known implementation of IB?

class FirstB : IB { }
class SecondB : IB { }
Debug.Assert(myDerivedAB is DerivedA<FirstB> || myDerivedAB is DerivedA<SecondB>) 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天暗了我发光 2024-12-01 17:49:20

尽管类型显然是兼容的

但它们不是;通过 out 实现的 C# 协变仅适用于接口和委托(引用类型,尽管这在这里很好)。它不适用于诸如 Derived 之类的类。

although the types clearly are compatible

No they aren't; C# covariance via out applies only to interfaces and delegates (of reference-types, although that is fine here). It does not apply to classes such as Derived<T>.

海夕 2024-12-01 17:49:20

您可以使用 Type 对象的 GetGenericArguments 方法:

Type t = myDerivedAB.GetType();
if (t.IsGenericType)
{
    Type[] typeArguments = t.GetGenericArguments();
    Debug.Assert(typeArguments.Length > 0 && typeArguments[0] is IB);
}

通过此您可以获得 myDerivedAB 对象的 Generic 参数,并检查其类型或您需要的其他内容。

You can use GetGenericArguments method of Type object:

Type t = myDerivedAB.GetType();
if (t.IsGenericType)
{
    Type[] typeArguments = t.GetGenericArguments();
    Debug.Assert(typeArguments.Length > 0 && typeArguments[0] is IB);
}

By this you can get the Generic parameter of the myDerivedAB object, and check its type, or something else you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文