【问题标题】:Using an inherited generic type as an input to a method of a type constrained class使用继承的泛型类型作为类型约束类的方法的输入
【发布时间】:2015-05-14 13:29:56
【问题描述】:

编辑:更改以使代码更好地识别问题。

我正在调整蒙特卡罗模拟的性能,其中将 IComponent 转换为 IProposition 会导致瓶颈。我想出一个建筑师来移除铸件,但它没有按预期工作。

TryDo中的方法调用抛出编译错误? (参数类型'IProposition 不可分配给参数类型'T') 为什么? (IProposition 满足对 T 的约束)以及如何解决?

using System.Collections.Generic;

public interface IComponent<T> where T : IComponent<T>
{
    HashSet<T> Inputs { get; }
}

public interface IProposition<T> : IComponent<T> where T : IComponent<T> { }

public interface IAnd<T> : IComponent<T> where T : IComponent<T> {}

class DoStuff<T> where T : IComponent<T>
{
    private void DoIt(T component)
    {
        if (component is IAnd<T>)
            foreach(T input in component.Inputs)
                DoIt(input);
    }

    void TryDo(IProposition<T> proposition)
    {
        DoIt(proposition);
    }
}

(我提出了一个单独的解决方案,它使用单独的类型 'TP' 来表示 IProposition - 但似乎是多余的,因为 IProposition 肯定是 IComposition 的子类)

【问题讨论】:

  • 请在发布问题时告诉我们编译错误。
  • 因为组件或介词都不是 T 类型(DoIt 期望的)。它们是 T 的 IComponent 和 T 的 IProposition 类型。您已经指定 T 是 T 的 IComponent 的事实不是编译器可以推断的。此外,T 的 IComponent 不是从 T 派生的。所以...是的。
  • 您可以尝试 casting 组件和命题到 T 看看是否会引发任何无效的强制转换异常。毕竟你有一个复杂的模型。
  • 说实话,您的模型非常令人困惑,IComponent&lt;T&gt; where T : IComponent&lt;T&gt;{}IProposition&lt;T&gt; : IComponent&lt;T&gt; where T : IComponent&lt;T&gt;{} 的目的是什么?你确定这是你想要的模型吗?
  • 另外,你能至少展示一下这些接口在现实世界中的一些可能的用法吗?因为基本上这个模型强制每个组件成为它自己的一个组件或某个其他组件的一个组件。它有什么意义?它解决或防止了哪些领域问题?也许不限制IComponent 中的T 参数(或限制为其他内容)以允许IComponent&lt;IDataAccessService&gt; 等实现会更有用。

标签: c# generics inheritance constraints


【解决方案1】:

我不确定你想用这样的模型完成什么,但是这个代码可以编译:

public interface IComponent<T> where T : IComponent<T> { }

public interface IProposition<T> : IComponent<T> where T : IComponent<T> { }

class DoStuff<T> where T : IComponent<T>
{
    private void DoIt(T component)
    {
    }

    void TryDo(T component, T proposition)
    {
        DoIt(component);
        DoIt(proposition);
    }
}

我不确定您是否完全了解泛型的工作原理。您似乎有一个想法,但我真的不明白这样的代码有什么实际用途。

现在不要误会我的意思,但您应该花时间学习泛型和一般的 c#,使用更简单的模型。您的代码中的错误是由简单地向 DoIt 方法提供错误类型引起的,这是一个非常初学者错误。

【讨论】:

  • 我已经通过删除无关代码来简化示例。 TryDo 签名将用法封装在更高级别,它是不可更改的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多