c# - 通用类型作为通用类型

标签 c# generics

我想在另一个泛型类型中使用一个泛型类型。

但出现以下异常:

The type 'MockManagers.ToPos' cannot be used as type parameter 'Res' in the generic type or method 'MockManagers.IMockManager<Req,Res>'. There is no implicit reference conversion from 'MockManagers.ToPos' to 'MockManagers.MockResponseObject<System.IComparable>'.

我尝试了几个选项来解决这个问题,但没有任何运气。 这reference建议将内部泛型类型作为参数传递给更高级别的泛型类型。这是唯一的解决方案吗?

代码:
我的界面:

/// <summary>
/// Represents IMockManager for mock object creation object.
/// </summary>
/// <typeparam name="Req">The request object Type.</typeparam>
/// <typeparam name="Res">The response object type.</typeparam>
public interface IMockManager<Req, Res>
    where Req : MockRequestObject
    where Res : MockResponseObject<IComparable>
{...//interface definitions}

对象实现:

/// <summary>
/// Represents Mock response for a request object
/// </summary>
public class ToPos : MockResponseObject<byte[]>
{... //implementation}

public class MockBaseObject
{
    public int Id { get; set; }
}

 public class MockResponseObject<T> : MockBaseObject
{
    /// <summary>
    /// The response content.
    /// </summary>
    public T Content { get; set; }

    /// <summary>
    /// Res creation date.
    /// </summary>
    public DateTime CreationDate { get; set; }
}

最佳答案

这里的问题是您需要类的通用方差。 C# 仅支持接口(interface)上的通用变体。

这是您似乎想要工作的简化版本:

// Works fine: "string" is compatible with "IComparable"
IComparable a = new string('a', 5);

// Error: "List<string>" is not compatible with List<IComparable>"
List<IComparable> b = new List<string>(); 

然而,这仅适用于接口(interface),并且仅当它们满足特定的方差约束时。一个这样的接口(interface)是 IEnumerable<out T>接口(interface):

// Works fine: IEnumerable is covariant
IEnumerable<IComparable> c = new List<string>();

// Similarly, IEnumerable<string> is compatible with IEnumerable<IComparable>:
IEnumerable<string> d = null;
IEnumerable<IComparable> e = d;

那么如何解决这个问题?这是一个想法。

首先,你不能使用byte[]因为它不是 IComparable .让我们使用 string作为一个例子,但你必须找到其他合适的东西来实现这个接口(interface)。

其次,制作MockResponseObject一个界面。此外,使其在 T协变:

public interface IMockResponseObject<out T>
{
    T Content { get; }
    DateTime CreationDate { get; set; }
}

为了让它工作,Content 无法通过界面设置

最后,更新其余代码以使用此接口(interface):

interface IMockManager<Req, Res>
    where Req : MockRequestObject
    where Res : IMockResponseObject<IComparable>
{
}

public class ToPos : MockBaseObject, IMockResponseObject<string>
{
    public string Content
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    public DateTime CreationDate
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }
}

观察 ToPos还有一个Content使用 setter:只要不通过界面就可以设置内容。

通过所有这些更改,以下内容现在有效并且可以正常编译:

static IMockManager<MockRequestObject, ToPos> manager = null;

关于c# - 通用类型作为通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11188854/

相关文章:

c# - 没有等待的嵌套异步方法 block

c# - 将 JSON 文件读入 Jarray 并动态访问数据

java - 通用方法类型参数

.net - 使用带有泛型类型参数的异常是好是坏

generics - Java 8 中的谓词接口(interface)

c# - 带有发布数据的 httplistener

c# - 带有附件/MIME 内容的 SOAP

java - 从抽象类实现比较器

c# - 从 MethodInfo 获取 Func<> 的 Delegate.CreateDelegate 不适用于 double 类型?

ios - 如何在 TableView 部分使用一个带有可选用例的枚举