我有一个通用类Zone<T> where T: Media.Medium。在这个类中,我有一个方法public void AddNode(Node node),其中有一个node.ParentZone = this引发此编译器错误的语句:
无法将类型“Zone< T >”隐式转换为“Zone< Media.Medium >”
但我不明白为什么 aspublic abstract class Node有public Zone<Media.Medium> ParentZone字段和类Zone<T> where T: Media.Medium受 约束where T: Media.Medium,所以 TMedia.Medium在任何情况下都是 a 。
这是独立的代码:(完整Zone<T>且相关部分Node)
public class Zone<T> where T: Media.Medium
{
public readonly Type MediaType = typeof(T);
public readonly Guid ID = new Guid();
private readonly List<Node> _nodes = new List<Node>();
public void AddNode(Node node)
{
foreach (var port in node.GetPorts())
{
port.Medium = Activator.CreateInstance<T>();
}
Run Code Online (Sandbox Code Playgroud)
// 下面这行编译错误
node.ParentZone = this;
Run Code Online (Sandbox Code Playgroud)
// 无法将类型 'Zone< T >' 隐式转换为 'Zone< Media.Medium >'
_nodes.Add(node);
}
public List<Node> GetNodes() => new List<Node>(_nodes);
public void RemoveNode(Node node) => _nodes.Remove(node);
}
public abstract class Node
{
public Zone<Media.Medium> ParentZone;
...
}
Run Code Online (Sandbox Code Playgroud)
更新#1:
这段代码的目标是:我想将Node对象添加到Zone对象,Zone对象有一个对象列表Node。每当我将 a 添加Node到 a时Zone,我想将该Zone对象设置为该对象的父对象Node。
我对实现这一目标的任何重构持开放态度。如果有更好的方式的话,它不应该是这样的。
您应该清楚,泛型约束不提供泛型类型之间的可分配性。或者以不同的方式表达:如果泛型类从另一个类继承并共享相同的类型参数,则它可以分配给另一个类。例如:
class Zone<T> where T : Medium { }
class ChildZone<T>: Zone<T> where T : Medium { }
class Medium { }
class ChildMedium : Medium { }
Run Code Online (Sandbox Code Playgroud)
什么有效:
Zone<Medium> mediumZone = new ChildZone<Medium>();
Zone<ChildMedium> childMediumZone = new ChildZone<ChildMedium>();
Run Code Online (Sandbox Code Playgroud)
什么不起作用:
Zone<Medium> mediumZone = new Zone<ChildMedium>();
ChildZone<Medium> childMediumZone = new ChildZone<ChildMedium>();
Run Code Online (Sandbox Code Playgroud)
为什么?因为继承在泛型类中起作用,而不是在泛型参数中起作用。考虑一下:
class Zone<T> {
T Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
的实例Zone<Medium>可以读取和Medium写入其属性中的类型的项目Value。这意味着它可以读取和写入Medium和ChildMedium。相比之下,Zone<ChildMedium>只能读取和写入ChildMedium。这里的问题是 setter,因为不可能分配Medium给Zone<ChildMedium>.Value,但不能分配给 to Zone<Medium>.Value。这使得类型不兼容。
如果您的Zone类是一个接口,并且您确保它只返回类型 T 的值,但您无法设置该类型的值,则可以使用协方差:
interface IZone<out T> {
T Value { get; }
}
Run Code Online (Sandbox Code Playgroud)
如果您需要读取和写入该值,您唯一的选择就是Node也通用并传递通用约束:
namespace Core.Nodes
{
public abstract class Node<T> where T : Media.Medium
{
public Zone<T> ParentZone;
//...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1518 次 |
| 最近记录: |