C# 基类为泛型时如何将派生对象设置为基类变量
在我的Silverlight 4应用程序中,我尝试使用泛型,但还有另一个问题,我希望在stackoverflow社区的帮助下解决: 我有一个树结构,可以有两种模式,编辑器模式,其中创建树,添加、移动、删除节点等,以及配置器模式,其中用户可以选择树的节点 为了表示树,我为两种模式创建了一个基类,并为每种模式创建了一个派生类。由于编辑器模式只能有编辑器节点,而配置器模式只能有配置器节点,因此我将基类设置为通用:C# 基类为泛型时如何将派生对象设置为基类变量,c#,generics,inheritance,C#,Generics,Inheritance,在我的Silverlight 4应用程序中,我尝试使用泛型,但还有另一个问题,我希望在stackoverflow社区的帮助下解决: 我有一个树结构,可以有两种模式,编辑器模式,其中创建树,添加、移动、删除节点等,以及配置器模式,其中用户可以选择树的节点 为了表示树,我为两种模式创建了一个基类,并为每种模式创建了一个派生类。由于编辑器模式只能有编辑器节点,而配置器模式只能有配置器节点,因此我将基类设置为通用: public abstract class ServiceModelBase<TR
public abstract class ServiceModelBase<TRootNodeType>
where TRootNodeType : ServiceNodeVMBase
{
public TRootNodeType RootNode
{
get { return _rootNode; }
}
...
}
public class ServiceModelConfigurator : ServiceModelBase<ServiceNodeVMConfigurator>
public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>
编译器告诉我,它无法在ServiceModelBase中转换ServiceModelEditor
谁能告诉我,我必须如何为EventArgs类编写代码,我可以将ServiceModelEditor或ServiceModelConfigurator分配给ServiceModel变量
PS:我很抱歉,这只是我提出的另一个与泛型相关的问题,但我担心泛型和我还不是真正的朋友。你可以使用:
您可以使用:
要使用协方差,必须声明协方差接口:
public interface IServiceModelBase<out TRootNode>
where TRootNode : ServiceNodeVMBase
{
TRootNode RootNode { get; }
}
public abstract class ServiceModelBase<TRootNode> : IServiceModelBase<TRootNode>
{
...
}
public class ServiceModelLoadedEventArgs : EventArgs
{
public IServiceModelBase<ServiceNodeVMBase> ServiceModel { get; set; }
...
}
public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>
要使用协方差,必须声明协方差接口:
public interface IServiceModelBase<out TRootNode>
where TRootNode : ServiceNodeVMBase
{
TRootNode RootNode { get; }
}
public abstract class ServiceModelBase<TRootNode> : IServiceModelBase<TRootNode>
{
...
}
public class ServiceModelLoadedEventArgs : EventArgs
{
public IServiceModelBase<ServiceNodeVMBase> ServiceModel { get; set; }
...
}
public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>
如果您遵循.NET命名约定并提供以T开头的类型参数名称,这将非常有帮助。如果不仔细检查,RootNodeType看起来像一个普通的类型名称,而不是类型参数名称。很抱歉!我不知道。我现在已将类型参数编辑为以T开头。如果您遵循.NET命名约定并提供以T开头的类型参数名称,这将非常有帮助。如果不仔细检查,RootNodeType看起来像一个普通的类型名称,而不是类型参数名称。对此,我深表歉意!我不知道。我已经编辑了类型参数,以T now开头。out只能用于接口和委托这是VS告诉我的。我目前正在阅读有关协方差和逆变的内容,据我所知,我需要为我的ServiceModelBase类创建一个接口。out只能用于接口和委托这是VS告诉我的。我目前正在阅读有关协方差和逆变的内容,据我所知,我需要为我的ServiceModelBase类创建一个接口。是的,这很有效,非常感谢!我昨天读过关于协变和逆变的书。我不清楚的是:为什么您需要使用接口或委托,而不能在公共类MyClass这样的普通类中定义逆变…@Aaginor Eric Lippert对这个问题的回答为什么C4.0中没有类的通用逆变?讨论这个问题。实现它似乎是一件非常头疼的事情,而且你不会比在类上实现协变接口获得更多的好处。啊,谢谢你的链接!我想我基本上理解了,问题是:无法设置泛型类型。这也意味着,我无法在接口中为RootNode定义setter,对吗?是的,这很有效,非常感谢!我昨天读过关于协变和逆变的书。我不清楚的是:为什么您需要使用接口或委托,而不能在公共类MyClass这样的普通类中定义逆变…@Aaginor Eric Lippert对这个问题的回答为什么C4.0中没有类的通用逆变?讨论这个问题。实现它似乎是一件非常头疼的事情,而且你不会比在类上实现协变接口获得更多的好处。啊,谢谢你的链接!我想我基本上理解了,问题是:无法设置泛型类型。这也意味着,我不能在接口中为RootNode定义setter,对吗?
public abstract class ServiceModelBase<out RootNodeType>
where RootNodeType : ServiceNodeVMBase
{
}
public interface IServiceModelBase<out TRootNode>
where TRootNode : ServiceNodeVMBase
{
TRootNode RootNode { get; }
}
public abstract class ServiceModelBase<TRootNode> : IServiceModelBase<TRootNode>
{
...
}
public class ServiceModelLoadedEventArgs : EventArgs
{
public IServiceModelBase<ServiceNodeVMBase> ServiceModel { get; set; }
...
}
public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>
ServiceModelLoadedEventArgs args = new ServiceModelLoadedEventArgs();
args.ServiceModel = new ServiceModelEditor();