将值与 C# 中的子类关联

     2023-02-23     135

关键词:

【中文标题】将值与 C# 中的子类关联【英文标题】:Associate a value with a subclass in c# 【发布时间】:2011-03-20 04:43:24 【问题描述】:

我有以下课程,我的问题在于它的 GetComponent 函数

class GameObject
 

    private List<GameComponent> _components = new List<GameComponent>();
    public void AddComponent(GameComponent component)
    void RemoveComponent(string name)
    public T GetComponent<T>(string name) where T : GameComponent



class GameComponent

    public string Name  get; set; 

所以在 GetComponent 中我想获取由name 标识的组件并将其作为 T 返回。

所以我会打电话NavigationComponent navigation = gameObject.GetComponent&lt;NavigationComponent&gt;("navigation"); 其中 NavigationComponent 将是 GameComponent 的子类

由于每个 NavigationComponent 实例只会具有相同的名称“导航”,我正在考虑是否可以做一些事情来将 GetComponent 简化为以下内容

NavigationComponent navigation = gameObject.GetComponent&lt;NavigationComponent&gt;();

提前致谢。

更新 1

我应该提一下,GameObject 的工作方式类似于一组 GameObject,由它们的名称标识,因此其中每个只能有一个。

所以要详细说明我们有class SimpleNavigation : GameComponent ...class AdvancedNavigation : GameComponent ...class SensorSystem : GameComponent ...

然后我会给 SimpleNavigation 和 AdvancedNavigation 命名为“navigation”,给 SensorSystem 命名为“sensor”

所以我不能在上面的例子中同时拥有 SimpleNavigation 和 AdvancedNavigation。

希望这是有道理的。

提前致谢。

附言我担心当没有太多收获和长期规范可能会改变时,我可能会设置太多约束,但这超出了我猜的问题范围

【问题讨论】:

你听说过依赖注入(IoC:控制反转)吗? 所以您想从GameComponent 的列表中获取NavigationComponent 不,我没有,我现在去查一下 @GenericTypeTea 是的,这是正确的 你使用的是什么版本的框架? 【参考方案1】:

更新:回应您的修改:

然后我会给 SimpleNavigation 和 高级导航名称 “导航”和到 SensorSystem 名称“传感器”

如果是这样的话,那你真的不能指望有这样的界面了……

public T GetComponent<T>() where T : GameComponent  

...因为多个GameComponent 对象类型可能共享相同的名称。所以你不能从类型推断名称。

为什么不改用enum 呢?那么你可能会有这样的事情:

public enum ComponentType

    Navigation,
    Sensor // etc.

而您的GameObject 类又可以持有Dictionary&lt;ComponentType, GameComponent&gt;

那么您的GetComponent 方法可能如下所示:

GameComponent GetComponent(ComponentType type)  

无论如何,这是一个想法......


我认为更有意义的是:

首先,如果您按名称查找,请使用Dictionary&lt;string, GameComponent&gt; 而不是List&lt;GameComponent&gt;。这将为您提供 O(1) 的查找时间,而不是 O(N)。

现在,如果您希望名称依赖于类型,请像这样定义您的 GameComponent 类:

class GameComponent

    public virtual string Name
    
        // You could also hard-code this or cache it
        // for better performance.
        get  return this.GetType().Name; 
    

然后您可以选择覆盖派生方法中的 Name 属性,如下所示:

class NavigationComponent : GameComponent

    public override string Name
    
        // This returns the same thing as GetType().Name,
        // but it's faster.
        get  return "NavigationComponent"; 
    

那么您的AddComponent 方法将是:

public void AddComponent(GameComponent component)

    _components.Add(component.Name, component);

你的GetComponent 方法很简单:

public T GetComponent<T>() where T : GameComponent

    return _components[typeof(T).Name] as T;

【讨论】:

我还没有输入你的代码,但是如果它不是静态的,我怎么能在类型上调用 .Name 呢? @Xtapodi:调用this.GetType().Name 将返回对象的type 名称(本身是System.Type 对象)。这通常没有意义,除非您已指定您实际上希望 GameComponent 对象的名称与其类型的名称相同。所以出于这个原因,Type.Name 属性正是您想要的。 感谢您的新更新。如果像虚拟静态方法这样的东西是可能的,那么我想我可以做到,我希望某些解决方案可能存在属性,它可能存在,但我想把它放在那里会是相当昂贵的性能明智的,我不会无论如何都能强制执行。但我从未使用过属性,所以我可能是错的。我可以强制 GameObject 子类具有 [ComponentType(string name)] 属性吗?【参考方案2】:

重写:

您已经提到 .Name 应该 作为属性保留在您的 GameComponent 类中——因此要考虑的一个选项是覆盖相等运算符以说“如果 @987654324 的两个实例@ 具有相同的名称,那么它们应该被视为相等”。结合使用OfType() 的Dave's suggestion,你会得到这样的结果:

class GameObject
 

  private List<GameComponent> _components = new List<GameComponent>();

  public T GetComponent<T>(string name) where T : GameComponent, new
  
    return
      (from c in _components.OfType<T>()
      where c == new T  Name = name 
      select c).FirstOrDefault();
  
 

class GameComponent

  public string Name  get; set; 

  public bool Equals(GameComponent other)
  
    if (ReferenceEquals(null, other))
    
      return false;
    
    if (ReferenceEquals(this, other))
    
      return true;
    
    return Equals(other.Name, Name);
  

  public override bool Equals(object obj)
  
    if (ReferenceEquals(null, obj))
    
      return false;
    
    if (ReferenceEquals(this, obj))
    
      return true;
    
    if (obj.GetType() != typeof(GameComponent))
    
      return false;
    
    return Equals((GameComponent)obj);
  

  public override int GetHashCode()
  
    return (Name != null ? Name.GetHashCode() : 0);
  

值得考虑是否要实施这种方法——它会影响任何相等检查(而不是引用检查)。然而,它是一种非常强大的能力,可以说“当 X 时,X 和 Y 应该被认为是相等的”——而等式重载让您可以在单个集中式主页(就在实体上)实现该逻辑。

【讨论】:

我已经实现了上面的方法,带有 FirstOrDefault 的 GetComponent 和一个 lamda,但我认为我不需要展示它,因为我真的想改变它。在第一个注释中,因为我想要拥有可能具有 NavigationComponent 和 SensesComponent 等的 GameObjects。在第二个注释中,为了避免从我调用它的地方投射它,我想调用它的代码行数更少。 啊,我不明白你的问题的意图。我已经用另一种方法更新了我的答案 - 在 this 情况下可能不是您需要的,但值得考虑【参考方案3】:

首先,如果所有 NavigationComponents 都具有相同的名称,您将如何区分它们?如果您只想返回单个 NavigationComponent,则需要一个唯一标识符。

您可以使用 OfType() 方法返回一个类型的所有实例:

var navigationComponents = _components.OfType&lt;NavigationComponent&gt;();

从那里,您可以通过一些唯一标识符选择单个 NavigationComponent:

NavigationComponent nc = navigationComponents.Where(n =&gt; n.Id == 1);

【讨论】:

啊非常好,这似乎是我要找的。到目前为止,我认为每种类型只需要一个组件,但并非所有游戏对象都具有相同的组件集,一个可能有导航和传感器,一个可能只有一个传感器等。 你的回答让我对我想要实现的目标有了更好的思考,我已经更新了这个问题。

如何将值与 MySQL 中列中的所有值聚合

】如何将值与MySQL中列中的所有值聚合【英文标题】:howcanIaggregationvalueswithallthevaluesfromacolumninMySQL【发布时间】:2021-04-1413:42:28【问题描述】:如果我有下面的表格:company|year|quarter|revenueA20191200A20193100B2019280B2019440我怎样才能让... 查看详情

在 MySql 中,有没有办法将值与列中的数字进行比较?

】在MySql中,有没有办法将值与列中的数字进行比较?【英文标题】:InMySqlisthereawaytocompareavaluetoonlythedigitsinacolumn?【发布时间】:2015-02-0919:11:44【问题描述】:当用户输入电话号码的一部分时,我需要比较并查找该部分电话号码... 查看详情

M Power Query - 通过将值与两个参考列进行比较,有条件地转换动态列数中的值

】MPowerQuery-通过将值与两个参考列进行比较,有条件地转换动态列数中的值【英文标题】:MPowerQuery-conditionallyconvertvaluesfromadynamicnumberofcolumnsbycomparingvaluesagainsttworeferencecolumns【发布时间】:2021-10-2709:49:09【问题描述】:我遇到了... 查看详情

构造函数中的 C# 默认值与序列化的两个构造函数相同

】构造函数中的C#默认值与序列化的两个构造函数相同【英文标题】:C#defaultvalueinconstructorsameastwoconstructorsforserialization【发布时间】:2011-12-2204:34:14【问题描述】:当我为构造函数提供默认值时publicMyClass(stringdescription=null)....这... 查看详情

将值与组进行比较 - 熊猫

】将值与组进行比较-熊猫【英文标题】:Comparingvalueswithgroups-pandas【发布时间】:2017-10-2311:53:24【问题描述】:首先,我有一个包含这些列的数据框:issue_date|issue|special|group多行可以包含相同的group。对于每个组,我想得到它的... 查看详情

sql如何将值与sql进行比较?(代码片段)

查看详情

将 DataTable 列值与行过滤器 C# 中的枚举进行比较

】将DataTable列值与行过滤器C#中的枚举进行比较【英文标题】:CompareDataTableColumnValuewithEnuminRowFilterC#【发布时间】:2017-08-0708:05:24【问题描述】:我有一个要使用DataView过滤的数据表。过滤条件基于枚举值和字符串数据表列值。... 查看详情

如何将值收集到数组中并将集合传递给 C# 中的 datagridview?

】如何将值收集到数组中并将集合传递给C#中的datagridview?【英文标题】:HowtocollectvaluesintoanarrayandpassthecollectiontodatagridviewinC#?【发布时间】:2019-09-2021:02:06【问题描述】:我正在使用C#在Asp.Net中开发一个自定义POS应用程序,我... 查看详情

使用 StartsWith 将值与字符串数组进行比较

】使用StartsWith将值与字符串数组进行比较【英文标题】:ComparevaluetoarrayofstringsusingStartsWith【发布时间】:2012-01-0415:59:59【问题描述】:我有一个数组:string[]exceptions=newstring[]"one",two","one_1","three";..我想说:varresult=fromcinmyCollection... 查看详情

将值与数组元素进行比较

】将值与数组元素进行比较【英文标题】:comparevaluetoarrayelement【发布时间】:2018-03-0512:46:44【问题描述】:当我得到用户输入cin&gt;&gt;x;和cin&gt;&gt;y;然后我想将此与数组“定位线”L1[i][j]进行比较,但是当我使用if语... 查看详情

SQL WHERE 子句将值与尾随空格匹配

】SQLWHERE子句将值与尾随空格匹配【英文标题】:SQLWHEREclausematchingvalueswithtrailingspaces【发布时间】:2011-05-0903:30:19【问题描述】:在SQLServer2008中,我有一个名为Zone的表,其中有一个列ZoneReferencevarchar(50)notnull作为主键。如果我运... 查看详情

将值与可能较大的数据集进行比较

】将值与可能较大的数据集进行比较【英文标题】:Compareavaluetoapotentiallylargedataset【发布时间】:2013-05-2821:49:58【问题描述】:我正在尝试找出最有效的方法来将一个值与一个潜在的巨大数据集进行比较。问题是我不知道我在寻... 查看详情

SQL将值与特定年份的平均值进行比较

】SQL将值与特定年份的平均值进行比较【英文标题】:SQLcomparingvaluetoaveragevalueforaspecificyear【发布时间】:2018-10-0318:18:30【问题描述】:期望的输出:我想选择1991年工资高于1991年平均水平的所有员工的头衔。当前代码:USEemployee... 查看详情

我应该如何在不使用 C++ 中的构造函数的情况下将值(不是指针)转换为子类?

】我应该如何在不使用C++中的构造函数的情况下将值(不是指针)转换为子类?【英文标题】:HowshouldIcastavalue(notapointer)toasubclasswithoutusingaconstructorinC++?【发布时间】:2015-02-1021:13:11【问题描述】:我有以下类打算用作值类型(... 查看详情

将值与mysql中表的所有字段进行比较[重复]

】将值与mysql中表的所有字段进行比较[重复]【英文标题】:comparevaluewithallthefieldsofatableinmysql[duplicate]【发布时间】:2011-09-0718:12:15【问题描述】:我有一个名为info_acc(id,state,country,zip)的表,现在我需要将一组关键字与该表的所... 查看详情

将值与mysql中表的所有字段进行比较[重复]

】将值与mysql中表的所有字段进行比较[重复]【英文标题】:comparevaluewithallthefieldsofatableinmysql[duplicate]【发布时间】:2011-09-0718:12:15【问题描述】:我有一个名为info_acc(id,state,country,zip)的表,现在我需要将一组关键字与该表的所... 查看详情

在 C# 中的服务器端将值转换为 NULL

】在C#中的服务器端将值转换为NULL【英文标题】:ConvertingaValuetoNULLonserversideinc#【发布时间】:2013-12-1912:06:03【问题描述】:我有一个使用存储过程填充网格的方法。SP从数据库表中获取数据,但其中一列将日期显示为“01/01/17540... 查看详情

如何将值与前导零或一般对齐?

】如何将值与前导零或一般对齐?【英文标题】:HowcanIalignavaluewithleadingzerooringeneral?【发布时间】:2021-12-0518:12:13【问题描述】:首先我只想说我是编程的初学者,因此我看到的许多问题的解决方案都太复杂了,我无法理解。我... 查看详情