我在玩《太空工程师》,这是一款允许在游戏中编写脚本的游戏。我想编写一个脚本,用某些物品类型重新填充船。
原始代码仅包含项目名称列表:
public readonly List<RequiredItem> requiredItemNames = new List<String>{
"ilder_Component/Construction",
"nt/Computer",
"_Component/Girder",
"ponent/MetalGrid",
"Motor",
"MyObjectBuilder_Component/SteelPlate",
};
但是我想为不同的物品取回不同的金额。我准备了以下结构式课程:
public class RequiredItem {
public RequiredItem(string pattern, double req) {
this.pattern = pattern;
this.amountRequired = req;
}
string pattern;
double amountRequired = 0;
}
我想初始化列表,但不使用重复的new RequiredItem("name", 12345)
。我在C ++中有点了解这种语法,但在C#中却不知道。我尝试了以下方法:
public readonly List<RequiredItem> requiredItemNames = new List<String>{
{"ilder_Component/Construction", 300}, // construction comp
{"nt/Computer",150},
{"_Component/Girder",100},
{"ponent/MetalGrid",70},
{"Motor",150},
{"MyObjectBuilder_Component/SteelPlate",333}
};
这给了我错误:
Error: No oveload for method 'Add' takes 2 arguments
因此,我想它正在尝试将这些对放入List.Add
而不是我的构造函数中。如何确定要构造的物品然后放入Add
中?
答案 0 :(得分:4)
作为迈克尔回答的替代方法,并且为了避免使用Builder
方法,您还可以依靠使用C#implicit keyword,例如:
public class RequiredItem
{
//snip
public static implicit operator RequiredItem((string pattern, double req) ri)
{
return new RequiredItem(ri.pattern, ri.req);
}
}
现在您可以使用元组创建列表:
public readonly List<RequiredItem> requiredItemNames = new List<RequiredItem>
{
("ilder_Component/Construction", 300), // construction comp
("nt/Computer",150),
("_Component/Girder",100),
("ponent/MetalGrid",70),
("Motor",150),
("MyObjectBuilder_Component/SteelPlate",333)
};
答案 1 :(得分:4)
集合初始值设定项仅需要具有兼容签名的Add
方法,并且该类型本身不必存在。 (不过,该集合必须实现IEnumerable
以“证明”它是一个集合。)
添加扩展方法...
public static class RequiredItemListExtensions
{
public static void Add(this List<RequiredItem> list, string pattern, double req)
{
list.Add(new RequiredItem(pattern, req));
}
}
然后,您可以按照自己的方式对其进行初始化。
public readonly List<RequiredItem> requiredItemNames = new List<RequiredItem>
{
{"ilder_Component/Construction", 300},
{"nt/Computer",150},
{"_Component/Girder",100},
{"ponent/MetalGrid",70},
{"Motor",150},
{"MyObjectBuilder_Component/SteelPlate",333}
};
我记得在实施Roslyn时,Microsoft能够删除阻止方法解析选择扩展方法的检查。这是Roslyn特定的更改,而不是版本特定的更改。在我的测试中,即使将LangVersion
属性降低到3.0(首次引入了集合初始值设定项,但尚未选择扩展方法),它仍然有效,而Roslyn之前的编译器仍会产生错误问题。
更新:已确认。我找到了VS 2013安装程序,尝试使用明确选择的版本5.0进行相同的代码,并且产生了相同的错误。我在VS 2015中加载了同一项目,仍选择了版本5.0,并进行了编译。太空工程师需要使用基于Roslyn的C#编译器才能发挥我的答案。
答案 2 :(得分:3)
您不能,对象和集合初始化器没有简化的语法来构造这样的对象列表。您需要指定类型。
但是,您可以使用命名元组
这样的操作荒谬public static List<RequiredItem> Builder(params (string pattern, double req)[] array)
=> array.Select(x => new RequiredItem(x.pattern, x.req)).ToList();
public readonly List<RequiredItem> requiredItemNames = Builder(
("ilder_Component/Construction", 300), // construction comp
("nt/Computer", 150),
("_Component/Girder", 100),
("ponent/MetalGrid", 70),
("Motor", 150),
("MyObjectBuilder_Component/SteelPlate", 333));
其他资源
C#元组是您使用轻量级语法定义的类型。的 优点包括语法更简单,基于以下内容的转换规则 元素的数量(称为基数)和类型,以及 复制,相等性测试和作业的一致规则。作为一个 权衡,元组不支持某些面向对象的习惯用法 与继承相关。
Object and Collection Initializers (C# Programming Guide)
C#可让您实例化对象或集合并执行成员 单个语句中分配作业。