首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型类型作为泛型类型

泛型类型作为泛型类型
EN

Stack Overflow用户
提问于 2012-06-25 11:52:49
回答 2查看 811关注 0票数 3

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

但是得到以下例外情况:

类型'MockManagers.ToPos'不能用作泛型类型或方法'MockManagers.IMockManager<Req,Res>'中的类型参数'Res'。不存在从'MockManagers.ToPos''MockManagers.MockResponseObject<System.IComparable>'的隐式引用转换。

我几乎没有办法解决这件事而没有任何运气。此reference建议将内部泛型类型作为参数传递给更高级别的泛型类型。这是唯一的解决办法吗?

守则:

我的界面:

代码语言:javascript
复制
/// <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}

对象实现:

代码语言:javascript
复制
/// <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; }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-25 15:16:04

这里的问题是,您需要类上的泛型方差。C#只支持接口上的泛型差异。

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

代码语言:javascript
复制
// 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>(); 

但是,只有在接口满足某些方差约束的情况下,才有可能做到这一点。其中一个接口是IEnumerable<out T>接口:

代码语言:javascript
复制
// 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为例,但您必须找到其他适合实现此接口的方法。

第二,使MockResponseObject成为一个接口。此外,在T中使其协变:

代码语言:javascript
复制
public interface IMockResponseObject<out T>
{
    T Content { get; }
    DateTime CreationDate { get; set; }
}

为了使其工作,Content不能通过接口进行设置。

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

代码语言:javascript
复制
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仍然有一个带有setter的Content:只要它不是通过接口设置,就可以设置内容。

通过所有这些更改,下面的内容现在是有效的,并且编译得很好:

代码语言:javascript
复制
static IMockManager<MockRequestObject, ToPos> manager = null;
票数 3
EN

Stack Overflow用户

发布于 2012-06-25 15:38:31

您只需声明ToPos来自MockResponseObject<IComparable>而不是MockResponseObject<byte[]>,但是可以使用新的byte[]类型隐藏Content属性。但是,要使其工作,您需要一些包装byte[]并实现IComparable的东西。例如:

代码语言:javascript
复制
public class ByteArrayComparable : IComparable
{
    public byte[] Data { get; private set; }
    public ByteArrayComparable(byte[] data) { Data = data; }

    // Implement IComparable.CompareTo() method here!
    public int CompareTo(object obj) { ... }
}

public class ToPos : MockResponseObject<IComparable>
{
    public new byte[] Content
    {
        get
        {
            if (base.Content == null)
                return null;
            return ((ByteArrayComparable) base.Content).Data;
        }
        set
        {
            base.Content = value == null ? null : new ByteArrayComparable(value);
        }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11188854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档