重载构造函数参数
Overloading constructor Params
考虑:
class MyList<T> {
public MyList(params T[] ts) { /* add all items to internal list */ }
public MyList(params IEnumerable<T>[] ets) { /* add all items from all enumerables to internal list */ }
}
然后
record Employee(string Name, int Age);
var l1 = new MyList<int>(1, 2, 3); // ok
IEnumerable<Employee> e = new List<Employee>() { new("John", 30), new("Eric", 30) };
var l2 = new MyList<Employee>(e, e); // ok
var l3 = new MyList<Employee>(
new("John", 30),
new("Eric", 30)
);
对于 l3
我得到:
The call is ambiguous between the following methods or properties: MyList<T>.MyList(params T[])
and MyList<T>.MyList(params IEnumerable<T>[])
我不明白为什么 l1
可以编译而 l3
不能编译?
有没有办法让这 3 个都起作用?
这与目标类型 new
的工作方式有关。从proposal开始,它具有以下特点:
A target_typed_new expression does not have a type. However, there is a new object creation conversion that is an implicit conversion from expression, that exists from a target_typed_new to every type.
在 MyList
的构造函数的重载解析期间,它查看 new("John", 30)
和 new("Eric", 30)
并发现存在从这些表达式到 Employee
和 Employee
的转换IEnumerable<Employee>
,所以两种重载都适用,而且哪一种都更好。因此调用不明确。
从这个意义上说,它有点像 null
字面量或 default
字面量,我怀疑 l3
不起作用,原因与此类似不工作:
var l3 = new MyList<Employee>(
default,
default
);
不过,文档还说:
The following are consequences of the specification:
- ...
- The following kinds of types are not permitted as targets of the conversion
- ...
- Interface types: This would work the same as the corresponding creation expression for COM types.
- ...
和IEnumerable<Employee>
是一个接口。
这表明“转换是否有效”是在重载解析之后进行的,这很奇怪。但接口是无效目标这一事实只是规范的“结果”,并没有明确指定(转换被指定为对所有类型有效,但由于target-typed new是一种对象创建表达式,你不能在对象创建表达式中使用接口) , 所以我想这在技术上没问题。
考虑:
class MyList<T> {
public MyList(params T[] ts) { /* add all items to internal list */ }
public MyList(params IEnumerable<T>[] ets) { /* add all items from all enumerables to internal list */ }
}
然后
record Employee(string Name, int Age);
var l1 = new MyList<int>(1, 2, 3); // ok
IEnumerable<Employee> e = new List<Employee>() { new("John", 30), new("Eric", 30) };
var l2 = new MyList<Employee>(e, e); // ok
var l3 = new MyList<Employee>(
new("John", 30),
new("Eric", 30)
);
对于 l3
我得到:
The call is ambiguous between the following methods or properties:
MyList<T>.MyList(params T[])
andMyList<T>.MyList(params IEnumerable<T>[])
我不明白为什么 l1
可以编译而 l3
不能编译?
有没有办法让这 3 个都起作用?
这与目标类型 new
的工作方式有关。从proposal开始,它具有以下特点:
A target_typed_new expression does not have a type. However, there is a new object creation conversion that is an implicit conversion from expression, that exists from a target_typed_new to every type.
在 MyList
的构造函数的重载解析期间,它查看 new("John", 30)
和 new("Eric", 30)
并发现存在从这些表达式到 Employee
和 Employee
的转换IEnumerable<Employee>
,所以两种重载都适用,而且哪一种都更好。因此调用不明确。
从这个意义上说,它有点像 null
字面量或 default
字面量,我怀疑 l3
不起作用,原因与此类似不工作:
var l3 = new MyList<Employee>(
default,
default
);
不过,文档还说:
The following are consequences of the specification:
- ...
- The following kinds of types are not permitted as targets of the conversion
- ...
- Interface types: This would work the same as the corresponding creation expression for COM types.
- ...
和IEnumerable<Employee>
是一个接口。
这表明“转换是否有效”是在重载解析之后进行的,这很奇怪。但接口是无效目标这一事实只是规范的“结果”,并没有明确指定(转换被指定为对所有类型有效,但由于target-typed new是一种对象创建表达式,你不能在对象创建表达式中使用接口) , 所以我想这在技术上没问题。