【问题标题】:Partial generic interface with type constraint具有类型约束的部分泛型接口
【发布时间】:2017-03-20 12:36:17
【问题描述】:

我需要创建两个部分接口。一个有约束,另一个没有,比如:

public partial interface IMyCuteInterface<T> where T : IEnumerable
{
    void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}

public partial interface IMyCuteInterface<T>
{
    void DoSomeStuff();
    void DoSomeStuff2();
}

这是实现:

public class CuteInterfaceImplementation<T> : IMyCuteInterface<T>
{
    private readonly T _element;
    public CuteInterfaceImplementation(T element)
    {
        _element = element;
    }

    public void DoSomethingOnlyPossibleIfGenericIsIEnumerable(){}
    public void DoSomeStuff(){}
    public void DoSomeStuff2() { }
}

这是一种更动态地获取它的静态方法:

public class CuteInterfaceImplementationBase
{
    public static IMyCuteInterface<T> From<T>(T t)
    {
        return new CuteInterfaceImplementation<T>(t);
    }
}

我想这样称呼它:

public static void Main(string[] args)
{
    var mci = CuteInterfaceImplementationBase.From(args);
}

所以,C# 想要我将我在第一个接口中添加的泛型类型约束添加到我的CuteInterfaceImplementationBase.From&lt;T&gt; 和我的CuteInterfaceImplementation&lt;T&gt;-class。

我想要实现的是:args 可以是例如来自List&lt;T&gt; 类型或int 类型或其他类型。我的目标是,如果args 来自IEnumerable&lt;T&gt; 类型,我想向CuteInterfaceImplementation-instance 添加更多功能(通过带有约束的接口)。

示例:

如果 args 来自类型 IEnumerable,则来自 CuteInterfaceImplementation 的此实例具有方法:

  • void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
  • void DoSomeStuff();
  • void DoSomeStuff2();

如果 args 来自 Foo 或 int 类型(或任何未实现 IEnumerable 的类型),我可以使用方法:

  • void DoSomeStuff();
  • void DoSomeStuff2();

表示DoSomethingOnlyPossibleIfGenericIsIEnumerable 不可用。

但这似乎是不可能的,因为我需要将约束添加到我实现的类中。知道怎么做吗?

【问题讨论】:

  • 我认为partial 的目的是拆分定义,而不是你想要的。
  • 如果你的类包含 DoSomethingOnlyPossibleIfGenericIsIEnumerable - 那么泛型应该是 IEnumerable,你应该不能将该类与任何其他类型一起使用(顺便说一下 partial 在这里无关紧要,可能你不明白partial 的真正作用)。
  • 对不起@Evk,但我知道 partial 的作用。你的评论只是重复了我所说的。是的,这是不可能的。我的问题是,我怎样才能让它发挥我在帖子中解释的作用。

标签: c# generics interface type-constraints


【解决方案1】:

不确定这种方法是不是好主意,它违反了 SOLID 中的“我” - interface segregation

不应强迫客户依赖它不使用的方法

您正在使用partial 拆分两个根本不同的接口,您应该有两个不同的接口,因为它们是不同的。

回答您的问题: 如果您致力于在T 的条件下采用类似的方法,您可以拆分接口,将“通用逻辑”(两个接口都使用)移动到基类并使用From&lt;T&gt; 方法有条件地选择哪个实现创建。

类似这样的:

public partial interface IMyCuteInterface_WITHEnumerable<T> : IMyCuteInterface<T> where T : IEnumerable
{
    void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}

public partial interface IMyCuteInterface<T>
{
    void DoSomeStuff();
    void DoSomeStuff2();
}

然后是实现:

public class CuteInterfaceImplementation<T> : CuteInterfaceImplementation_COMMON<T>
{
    public CuteInterfaceImplementation(T element) : base(element)
    {

    }
}

public class CuteInterfaceImplementation_COMMON<T> : IMyCuteInterface<T>
{
    private readonly T _element;
    public CuteInterfaceImplementation_COMMON(T element)
    {
        _element = element;
    }
    public void DoSomeStuff() { }
    public void DoSomeStuff2() { }
}

public class CuteInterfaceImplementation_WITHEnumerable<T> : CuteInterfaceImplementation_COMMON<T>,  IMyCuteInterface_WITHEnumerable<T> where T : IEnumerable
{
    private readonly T _element;
    public CuteInterfaceImplementation_WITHEnumerable(T element) : base(element)
    {
        _element = element;
    }

    public void DoSomethingOnlyPossibleIfGenericIsIEnumerable() { }
}

最后是你的“静态助手”,它决定要实例化的类: 不幸的是,在 C# 中不可能有条件地实例化不同的类,因为一个期望 T 是 IEnumerable 而另一个不是。你可以使用dynamic

来解决这个问题
public class CuteInterfaceImplementation_HELPER
{
    public static IMyCuteInterface<T> From<T>(T t)
    {
        if (t is IEnumerable)
        {
            dynamic dyn = t;
            return FromEnumerable(dyn);
        }
        else
        {
            return new CuteInterfaceImplementation<T>(t);
        }
    }

    public static IMyCuteInterface<T> FromEnumerable<T>(T t) where T: IEnumerable
    {
        return new CuteInterfaceImplementation_WITHEnumerable<T>(t);
    }
}

【讨论】:

  • 嗯,是的......你绝对是对的。从基接口继承是更好的方法。我需要稍微更改一下我的代码。谢谢!
猜你喜欢
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多