我喜欢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) { }
}
现在我的问题是:对于HandleOut
,TInner
的类型由“Out”类型给出,那么有没有办法将HandleOut
的定义简化为类似public class HandleOut : Handler<Out>
并且仍然可以将内部类型用作SetValue
的参数?
这是一个非常简单的例子,但我有时在定义中得到一长串泛型类型,通常所有这些类型都可以从第一种类型中逻辑推导出来。我有什么诡计吗?
答案 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>>
。