我想在另一种泛型中使用泛型类型。
但获得以下异常:
类型
'MockManagers.ToPos'
不能用作泛型类型或方法'Res'
中的类型参数'MockManagers.IMockManager<Req,Res>'
。 没有从'MockManagers.ToPos'
到'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; }
}
答案 0 :(得分:3)
这里的问题是你想要一个类的泛型方差。 C#仅支持接口上的泛型差异。
以下是您似乎想要工作的简化版本:
// 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>
接口:
// 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
:
public interface IMockResponseObject<out T>
{
T Content { get; }
DateTime CreationDate { get; set; }
}
为了使其正常工作,Content
无法通过界面进行设置。
最后,更新其余代码以使用此界面:
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
带有设定者:只要不是通过界面,您就可以设置内容。
通过所有这些更改,以下内容现在有效并且编译正常:
static IMockManager<MockRequestObject, ToPos> manager = null;
答案 1 :(得分:2)
您可以将ToPos
声明为源自MockResponseObject<IComparable>
而不是MockResponseObject<byte[]>
,但随后使用Content
类型的新属性隐藏byte[]
属性。但是,要实现此功能,您需要包含byte[]
并实现IComparable
的内容。例如:
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);
}
}
}