Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.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# 如何从列表中获取指定值<;T>;T是一个泛型类?_C#_Generics_Reflection - Fatal编程技术网

C# 如何从列表中获取指定值<;T>;T是一个泛型类?

C# 如何从列表中获取指定值<;T>;T是一个泛型类?,c#,generics,reflection,C#,Generics,Reflection,假设我们有一个带有泛型数组的容器类 public class Container<T> { public T[] ObjectArray = new T[]; } public class PlayerInfo { public int level; public string playerName; public string description } public class EnemyInfo { public string ene

假设我们有一个带有泛型数组的容器类

public class Container<T>
{
    public T[] ObjectArray = new T[];
}

public class PlayerInfo
{
    public int level;
    public string playerName;
    public string description
}

public class EnemyInfo
{
    public string enemyName;
}


现在我可以想办法用反射做点什么,但也许还有另一种方法吗?

好吧,如果你想从特定类型中获取特定属性,例如
EnemyInfo
中的
enemyName
,对player也是如此(因此他们不会共享基类中的属性),我想你需要投下他们/检查类型,然后采取相应的行动

这样做应该可以:

foreach(var element in list)
{
   if(element is EnemyInfo enemy)
   {
     // print out 
     enemy.enemyName
   }
   else if(element is PlayerInfo player)
   {
     // print out
     player.playerName;
     player.description;
   }
}
foreach(var element in list)
{
  print element.EntityName;

  // Then cast if necessary for more specific types.


   if(element is EnemyInfo enemy)
   {
    /// ...
   }
   else if(element is PlayerInfo player)
   {
    /// ...
    player.description;
   }
}
作为一般建议,因为敌人和玩家都有一个名字,所以要有一个基类f.e.BaseInfo,它有一个专有的名字,玩家和敌人可以从中继承,所以如果你只想得到名字,你不需要施放:

public class BaseInfo
{
    public string EntityName;
}

public class PlayerInfo : BaseInfo
{
    public int level;
    public string description
}

public class EnemyInfo : BaseInfo
{
  // Have more specific enemy stuff here....
}
然后,您可以执行以下操作: 这样做应该可以:

foreach(var element in list)
{
   if(element is EnemyInfo enemy)
   {
     // print out 
     enemy.enemyName
   }
   else if(element is PlayerInfo player)
   {
     // print out
     player.playerName;
     player.description;
   }
}
foreach(var element in list)
{
  print element.EntityName;

  // Then cast if necessary for more specific types.


   if(element is EnemyInfo enemy)
   {
    /// ...
   }
   else if(element is PlayerInfo player)
   {
    /// ...
    player.description;
   }
}

如果您想要对象的字符串表示,一个简单且易于理解的解决方案是将其转换为JSON字符串:

foreach (var item in container.ObjectArray)
{
    Console.WriteLine(JsonConvert.SerializeObject(item));
}
这将为每个项目输出一个字符串,每个字符串包含每个项目的所有属性,而不管类型如何


如果您不喜欢JSON格式,则必须决定自己的自定义格式,并编写自己的序列化程序(最终可能不得不使用反射)。但原则将保持不变。

这是否回答了您的问题?我认为更好的方法是不要有无意义的超泛型容器类。如果您需要一个集合来保存
PlayerInfo
s,请声明一个集合;如果出于某种原因必须在一个位置存储多个不同类型的容器,那么可以使用一个类来保存多个类型属性(每个类型属性本身都可以是容器、字典或其他类型)。我很难想象实际场景中存储多个容器是有意义的,每个容器在一个地方都有不同的、不兼容的类型,并且仍然有意义地处理它们给出有意义的表示,并称之为;这有利于为任何
对象
工作。编写一个泛型的
.ToString()
,使用反射来计算所有属性值也不是很难,所以如果您不想的话,您不必为每个类都重做它。理想情况下,这会更有意义,但事实上,我有数百个类似于PlayerInfo的类,不可能逐个处理。因此,我仍然需要一种更通用的方法来实现这一点:(.对象的字符串表示不是我需要的。我需要对象中“字符串”类型的字段(例如playerName,但不是level)。