繁体   English   中英

C#通用接口无法实现

[英]c# generic interface impossible to implement

在我正在开发的库中,我需要多个不相关的类型来为(可能很多)“标签”提供值。 每个标记都有一个关联的值类型,并表示为(单个)类,它继承了以下通用基数:

public abstract class Tag<TTag,TValue>
  where TTag: Tag<TTag,TValue>
{
}

(类型参数TTag使用好奇重复模板模式)。

我想提供一个接口IProvider<TTag> ,它将标记可以为特定标签提供值的类。 理想情况下,界面应如下所示:

public interface IProvider<TTag>
{
  TValue GetValue<TValue>(Tag<TTag,TValue> tag);
}

这将允许从提供的标签中推断出值的类型(如果一个类型是多个标签的提供者)。 不幸的是,使用类Tag<TTag,TValue>要求约束TTag: Tag<TTag,TValue> ,该方法不能在此方法上指定,因为其唯一的通用参数是TValue 我尝试这样做:

public interface IProvider<TTag>
{
  TValue GetValue<TTag2,TValue>(Tag<TTag2,TValue> tag)
    where TTag2: Tag<TTag2,TValue>, TTag;
}

我的本意是,如果TTag是一个标签类继承Tag<TTag,TValue> ,对于唯一的办法TTag2满足这些约束条件是等于TTag 用这种方式编写的接口可以正确编译。 但是,实现会带来问题:

public struct Data<TTag,TValue> : IProvider<TTag>
  where TTag: Tag<TTag,TValue>
{
  public TValue Value;

  public TValue2 GetValue<TTag2,TValue2>(Tag<TTag2,TValue2> tag)
    where TTag2: Tag<TTag2,TValue2>, TTag
  {
    return (TValue2) Value;
  }
}

由于类型TTag2继承了两个不相关的类约束Tag<TTag2,TValue2>Tag<TTag,TValue> (语言规则没有注意到它们必须相等的“明显”事实),因此上述代码无法通过错误CS0455进行编译。 。 使该方法显式实现接口...使编译器(单声道3.2.8)崩溃。

经过漫长的介绍之后,我想到了一个问题:是否有可能在不牺牲任何(希望现在直觉上很清楚)约束的情况下提出IProvider<TTag>的可实现定义? 如果不是,您可以为原始方案建议不同的类型层次结构吗? 谢谢!

PS让我排除所有提及将标记的值类型作为IProvider的通用参数的实现-实际的值类型足够复杂,因此无法推断它们完全无法使用该库。

据我所知,该结构发生的地方是在Data结构中,您说的是在GetValue方法TValue2字段TValue Value作为TValue2返回。 它不是同一类型。

因此,我要做的唯一一件事就是做到这一点:

public abstract class Tag<TTag, TValue>
    where TTag: Tag<TTag,TValue>
{
}

public interface IProvider<TTag, TValue>
    where TTag: Tag<TTag,TValue>
{
    TValue GetValue(TTag tag);
}

public struct Data<TTag, TValue> : IProvider<TTag, TValue>
    where TTag: Tag<TTag, TValue>
{
    public TValue Value;

    public TValue GetValue(TTag tag)
    {
        return Value;
    }
}

但这与您在问题中的要求相冲突。

这使您更加接近:

public interface IProvider<TTag>
{
    TValue GetValue<T, TValue>(T tag) where T : Tag<T, TValue>;
}

public struct Data<TTag, TValue> : IProvider<TTag>
{
    public TValue Value;

    public TV GetValue<T, TV>(T tag) where T : Tag<T, TV>
    {
        return (TV)(object)Value;
    }
}

但是这里的问题还是行return (TV)(object)Value; -您不能将TValue的值转换为TV因为此代码的全部目的是使GetValue方法的返回类型保持自由。 但这是不可能的。

您必须在IProvider接口上具有TValue参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM