[英]How can I use a generic type parameter for different structs that have a variable with the same type and name?
I have a method, ListToString
, that takes a list and outputs the name
element of all structs in the list. 我有一个方法
ListToString
,它接受一个列表并输出列表中所有结构的name
元素。 Each struct that I use ListToString
for has a name element, but because I can't apply name
to a generic type, I need to create an overload of ListToString
for each struct. 我使用
ListToString
每个结构都有一个name元素,但是由于无法将name
应用于通用类型,因此需要为每个结构创建ListToString
的重载。 This has cost me about a hundred lines. 这花了我大约一百行。
Example of what I want to happen: 我想发生的事的例子:
public static string ListToString<T>(List<T> list, bool formatted)
{
//Throws many errors because 'T' does not have a 'name' element
string returnString = "";
if (formatted)
{
if(list.Count == 1)
{
returnString += list[0].name;
}
else if(list.Count == 2)
{
returnString = list[0].name + " and a " + list[1].name;
}
else
{
for(int i = 0; i < list.Count - 2; i++)
{
returnString += list[i].name + ", ";
}
returnString += "and a " + list[list.Count - 1].name;
}
}
What happens instead: 相反会发生什么:
public static string ListToString(List<World.Entities.Resource> list, bool formatted)
{
string returnString = "";
if (formatted)
{
if(list.Count == 1)
{
returnString += list[0].name;
}
else if(list.Count == 2)
{
returnString = list[0].name + " and a " + list[1].name;
}
else
{
for(int i = 0; i < list.Count - 2; i++)
{
returnString += list[i].name + ", ";
}
returnString += "and a " + list[list.Count - 1].name;
}
}
else
{
foreach (World.Entities.Resource resource in list)
{
returnString += resource.name + ", ";
}
}
return CapitalizeString(returnString);
}
public static string ListToString(List<World.Entities.Creature> list, bool formatted)
{
string returnString = "";
if (formatted)
{
if (list.Count == 1)
{
returnString += list[0].name;
}
else if (list.Count == 2)
{
returnString = list[0].name + " and a " + list[1].name;
}
else
{
for (int i = 0; i < list.Count - 2; i++)
{
returnString += list[i].name + ", ";
}
returnString += "and a " + list[list.Count - 1].name;
}
}
else
{
foreach (World.Entities.Creature creature in list)
{
returnString += creature.name + ", ";
}
}
return CapitalizeString(returnString);
}
public static string ListToString(List<World.Entities.Structure> list, bool formatted)
{
string returnString = "";
if (formatted)
{
if (list.Count == 1)
{
returnString += list[0].name;
}
else if (list.Count == 2)
{
returnString = list[0].name + " and a " + list[1].name;
}
else
{
for (int i = 0; i < list.Count - 2; i++)
{
returnString += list[i].name + ", ";
}
returnString += "and a " + list[list.Count - 1].name;
}
}
else
{
foreach (World.Entities.Structure structure in list)
{
returnString += structure.name + ", ";
}
}
return CapitalizeString(returnString);
}
public static string ListToString(List<World.Tools.Tool> list, bool formatted)
{
string returnString = "";
if (formatted)
{
if (list.Count == 1)
{
returnString += list[0].name;
}
else if (list.Count == 2)
{
returnString = list[0].name + " and a " + list[1].name;
}
else
{
for (int i = 0; i < list.Count - 2; i++)
{
returnString += list[i].name + ", ";
}
returnString += "and a " + list[list.Count - 1].name;
}
}
else
{
foreach (World.Tools.Tool tool in list)
{
returnString += tool.name + ", ";
}
}
return CapitalizeString(returnString);
}
Each struct has a similar name
element, so how can I incorporate a generic parameter to this? 每个结构都有一个相似的
name
元素,那么如何将通用参数并入呢?
Seems like you're coming form a language which uses duck typing , ie if an object has a property called name
, then any code knowing this fact can access this property without knowing the concrete type of the class. 好像您正在使用一种使用鸭子类型的语言,即,如果对象具有名为
name
的属性,则任何知道此事实的代码都可以访问此属性而无需知道类的具体类型。
Things don't quite work the same way in c# ( dynamic
aside). 在c#中,事情并非完全一样(
dynamic
除外)。 The idiomatic ways of implementing this pattern are either to derive all the relevant structs from a similar base type, or probably more suitable for your case, to have all structs implement an interface, eg IName
, which has a property Name
, and then add a generic constraint to your method, such as: 实现此模式的惯用方式是从相似的基本类型中派生所有相关的结构,或者可能更适合您的情况,以使所有结构实现一个接口,例如
IName
,该接口具有一个Name
属性,然后添加一个方法的一般约束 ,例如:
public interface IName
{
string Name { get; }
}
public struct Creature : IName
{
...
}
public static string ListToString<T>(List<T> list, bool formatted) where T : IName
{
... //The compiler now knows that T is guaranteed to implement IName.
}
You can add a generic constraint: 您可以添加通用约束:
public interface IThingWithAName
{
string name { get;}
}
Make sure your classes implement IThingWithAName and 确保您的类实现了IThingWithAName和
public static string ListToString<T>(List<T> list, bool formatted)
where T : IThingWithAName
{
// Now you can use list[0].name
}
also since you're not modifying the list, you can use: 另外,由于您没有修改列表,因此可以使用:
public static string ListToString<T>(IReadOnlyList<T> list, bool formatted)
where T : IThingWithAName
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.