是否可以简化C#中的嵌套泛型?

Chr*_*ygg 6 c# generics

我喜欢C#中的泛型,但有时与它们一起工作会变得有点复杂.下面的问题我时不时地遇到.有没有办法让这个场景更简单?我看不出怎么样,但我希望有人可以:)

给出三个基类:

public abstract class Inner
{
}

public abstract class Outer<T>
    where T : Inner
{
}

public abstract class Handler<TOuter, TInner>
    where TOuter : Outer<TInner>
    where TInner : Inner
{
    public abstract void SetValue(TInner value);
}
Run Code Online (Sandbox Code Playgroud)

还有一些简单的实现:

public class In : Inner
{
}

public class Out : Outer<In>
{
}

public class HandleOut : Handler<Out, In>
{
    public override void SetValue(In value) { }
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:For HandleOut,类型TInner是由"Out"类型给出的,那么是否有任何方法可以简化HandleOut类似的定义public class HandleOut : Handler<Out>并仍然能够使用内部类型作为参数SetValue

这是一个非常简单的例子,但我有时在定义中得到一长串泛型类型,通常所有这些类型都可以从第一种类型中逻辑推导出来.我有什么诡计吗?

The*_*aot 1

不。

虽然这样的推论可能是可能的,但它不是语言的一部分。您可能有兴趣向Roslyn提出这个建议(打开一个新问题)。当然,这种类型的通用约束推断在复杂的情况下可能会遇到问题,但至少对于简单的情况是可行的......但是,这是 C# 团队应该投入时间和精力的地方吗?

Damien_The_Unknowner在评论中分享的链接“为什么通用约束不被继承”是正确的。


无论如何,在您提供的代码中,虽然确实Out已经为您提供了 type ,但不需要通用In参数。TOuter

下面的代码同样有效:

public abstract class Inner
{
}

public abstract class Outer<T>
    where T : Inner
{
}

public abstract class Handler<TInner> // NOTE: TOuter removed
    where TInner : Inner
{
    public abstract void SetValue(TInner value);
}

public class In : Inner
{
}

public class Out : Outer<In>
{
}

public class HandleOut : Handler<In> // NOTE: Out removed
{
    public override void SetValue(In value) { }
}
Run Code Online (Sandbox Code Playgroud)

因此,Outer<TInner>如果需要,可以考虑使用 TOuter 来代替。当然,如果您保留一个列表,那么TOuter限制会更少,因为它将允许任何派生类型Outer<TInner>而不是任何派生类型TOuter

由于您没有在通用约束中添加“new”,因此您不会创建这种类型的对象,但如果情况到达,您可以Func<Outer<TInner>>在构造函数中接受 a 。