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

时间:2015-12-29 06:29:45

标签: 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);
}

一些简单的实现:

public class In : Inner
{
}

public class Out : Outer<In>
{
}

public class HandleOut : Handler<Out, In>
{
    public override void SetValue(In value) { }
}

现在我的问题是:对于HandleOutTInner的类型由“Out”类型给出,那么有没有办法将HandleOut的定义简化为类似public class HandleOut : Handler<Out>并且仍然可以将内部类型用作SetValue的参数?

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

1 个答案:

答案 0 :(得分:1)

没有

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

Why are generic constraints not inherited Damien_The_Unbeliever所在的链接shared on the comments

无论如何,在Out已经为您提供类型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) { }
}

因此,如果您需要,可以考虑使用Outer<TInner>而不是TOuter。当然,如果您保留TOuter列表,则限制性会更小,因为它允许任何派生类型的Outer<TInner>而不是任何派生类型的TOuter

因为你没有把&#34;新的&#34;在泛型约束中,您不是在创建此类型的对象,但如果案例到达,您可以在构造函数中接受Func<Outer<TInner>>