题
我的印象是,C#编译器将隐式地键入基于它们都可以隐式转换为的类型的数组。
编译器生成没有最佳类型用于隐式型阵列
public interface ISomething {}
public interface ISomething2 {}
public interface ISomething3 {}
public class Foo : ISomething { }
public class Bar : ISomething, ISomething2 { }
public class Car : ISomething, ISomething3 { }
void Main()
{
var obj1 = new Foo();
var obj2 = new Bar();
var obj3 = new Car();
var objects= new [] { obj1, obj2, obj3 };
}
我知道纠正此问题的方法是声明类型:
new ISomething [] { obj1, ...}
但是我在这里采用封面类型的帮助。
解决方案
C#编译器考虑了所有指定元素的类型集。确实如此 不是 考虑常见的基本类型等。
你 可以 施放其中一种表达方式:
var objects= new [] { obj1, obj2, (ISomething) obj3 };
...但是就个人而言,我只是使用明确的表格:
var objects= new ISomething[] { obj1, obj2, obj3 };
另外,如果您明确声明任何或全部 obj1
, obj2
和 obj3
作为类型 ISomething
, ,如果不更改数组初始化表达式,那也可以正常工作。
从C#3规格,第7.5.10.4节:
第三形式的数组创建表达式称为 隐式键入阵列创建表达式. 。它类似于第二种形式,只是没有明确给出数组的元素类型,而是确定为数组初始化器中表达式集的最佳常见类型(§7.4.2.13)。
第7.4.2.13节看起来像这样:
在某些情况下,需要推断一组表达式的普通类型。特别是,以这种方式找到了隐式键入数组的元素类型和带有块体的匿名函数的返回类型。直观地,给定一组表达式e1…em这个推论应该等同于调用方法
Tr M<X>(X x1 … X xm)
以EI为论点。更确切地说,推理从未固定的类型变量X开始。然后,通过X型X进行输出类型的推断。最后,X固定,结果类型S是表达式所得的公共类型。
其他提示
如果所有实例都可以施放到任何一个实例的类型中,则将使用该类型。对于所有实例,都没有任何类型的共同点,否则含义数组初始化将始终成功并经常产生不希望的 new object[]
数组。
是对飞碟的答复的略有补充:
您可以将其中一个数组项投入到所需的类型(在这种情况下接口),或者如果您只有该类型的单个元素(不是派生而是直接类型)。如
public static IWindsorInstaller[] MobileRestComponentInstallers
{
get
{
return new []
{
new RepositoryInstaller(),
new AppSettingsInstaller(),
// tens of other installers...
GetLoggerInstaller() // public IWindsorInstaller GetLoggerInstaller()...
};
}
}
这将起作用,但请不要那样做:)只是定义数组类型并更改 new[]
到 new IWindsorinstaller[]
。具有明确定义的数组类型更可读性。
Do like this for Class object( UIViewController) initialization in var array:
var page1 = new Class1();
var page2 = new Class2();
var pages = new UIViewController[] { page1, page2 };
注意:这里的UiviewController可以是任何类