使用简短的初始化语法来初始化对值列表
Use short initializer syntax to initialize a list of pair values
我在玩 Space 工程师,这是一款允许在游戏中编写脚本的游戏。我想编写一个脚本,用某些类型的物品重新装满一艘船。
原始代码只有项目名称列表:
public readonly List<RequiredItem> requiredItemNames = new List<String>{
"ilder_Component/Construction",
"nt/Computer",
"_Component/Girder",
"ponent/MetalGrid",
"Motor",
"MyObjectBuilder_Component/SteelPlate",
};
但我想为不同的项目检索不同的金额。我准备了以下结构 class:
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
?
你不能,对象和集合初始化程序 没有简写语法来构造这样的对象列表。您需要指定 type.
但是,您可以使用 命名元组
来做一些荒谬的事情
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# tuples are types that you define using a lightweight syntax. The
advantages include a simpler syntax, rules for conversions based on
number (referred to as cardinality) and types of elements, and
consistent rules for copies, equality tests, and assignments. As a
tradeoff, tuples do not support some of the object-oriented idioms
associated with inheritance.
Object and Collection Initializers (C# Programming Guide)
C# lets you instantiate an object or collection and perform member
assignments in a single statement.
作为 Michael 答案的替代方案,为了避免使用 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)
};
集合初始值设定项只需要一个具有 兼容签名 的 Add
方法,并且它不必存在于类型本身上。 (该集合必须实现 IEnumerable
到 "prove" 它是一个集合。)
添加扩展方法...
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 版,并进行了编译。 Space 工程师需要使用基于 Roslyn 的 C# 编译器才能使我的回答生效。
我在玩 Space 工程师,这是一款允许在游戏中编写脚本的游戏。我想编写一个脚本,用某些类型的物品重新装满一艘船。
原始代码只有项目名称列表:
public readonly List<RequiredItem> requiredItemNames = new List<String>{
"ilder_Component/Construction",
"nt/Computer",
"_Component/Girder",
"ponent/MetalGrid",
"Motor",
"MyObjectBuilder_Component/SteelPlate",
};
但我想为不同的项目检索不同的金额。我准备了以下结构 class:
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
?
你不能,对象和集合初始化程序 没有简写语法来构造这样的对象列表。您需要指定 type.
但是,您可以使用 命名元组
来做一些荒谬的事情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# tuples are types that you define using a lightweight syntax. The advantages include a simpler syntax, rules for conversions based on number (referred to as cardinality) and types of elements, and consistent rules for copies, equality tests, and assignments. As a tradeoff, tuples do not support some of the object-oriented idioms associated with inheritance.
Object and Collection Initializers (C# Programming Guide)
C# lets you instantiate an object or collection and perform member assignments in a single statement.
作为 Michael 答案的替代方案,为了避免使用 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)
};
集合初始值设定项只需要一个具有 兼容签名 的 Add
方法,并且它不必存在于类型本身上。 (该集合必须实现 IEnumerable
到 "prove" 它是一个集合。)
添加扩展方法...
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 版,并进行了编译。 Space 工程师需要使用基于 Roslyn 的 C# 编译器才能使我的回答生效。