Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基类为泛型时如何将派生对象设置为基类变量_C#_Generics_Inheritance - Fatal编程技术网

C# 基类为泛型时如何将派生对象设置为基类变量

C# 基类为泛型时如何将派生对象设置为基类变量,c#,generics,inheritance,C#,Generics,Inheritance,在我的Silverlight 4应用程序中,我尝试使用泛型,但还有另一个问题,我希望在stackoverflow社区的帮助下解决: 我有一个树结构,可以有两种模式,编辑器模式,其中创建树,添加、移动、删除节点等,以及配置器模式,其中用户可以选择树的节点 为了表示树,我为两种模式创建了一个基类,并为每种模式创建了一个派生类。由于编辑器模式只能有编辑器节点,而配置器模式只能有配置器节点,因此我将基类设置为通用: public abstract class ServiceModelBase<TR

在我的Silverlight 4应用程序中,我尝试使用泛型,但还有另一个问题,我希望在stackoverflow社区的帮助下解决:

我有一个树结构,可以有两种模式,编辑器模式,其中创建树,添加、移动、删除节点等,以及配置器模式,其中用户可以选择树的节点

为了表示树,我为两种模式创建了一个基类,并为每种模式创建了一个派生类。由于编辑器模式只能有编辑器节点,而配置器模式只能有配置器节点,因此我将基类设置为通用:

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();