我的印象是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, ...}
但是我在这里打了一个封面类型的帮助。
答案 0 :(得分:14)
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. 然后进行输出类型推断 来自每个Ei的X型。最后,X 是固定的,结果类型S是 由此产生的共同类型 表达式。
答案 1 :(得分:3)
如果实例都可以转换为任何一个实例的类型,那么将使用该类型。所有实例都没有共同的任何类型是不够的,否则隐含数组初始化将始终成功,并且通常会生成不需要的new object[]
数组。
答案 2 :(得分:0)
作为Skeet的回复的一点点补充:
您可以将其中一个数组项转换为您需要的类型(在本例中为interface),或者如果您只有一个该类型的元素(不是派生而是直接类型)。如
public static IWindsorInstaller[] MobileRestComponentInstallers
{
get
{
return new []
{
new RepositoryInstaller(),
new AppSettingsInstaller(),
// tens of other installers...
GetLoggerInstaller() // public IWindsorInstaller GetLoggerInstaller()...
};
}
}
这样可行,但请不要这样做:)只需定义数组类型并将new[]
更改为new IWindsorinstaller[]
即可。
在显式定义数组类型的情况下,它更具可读性。
答案 3 :(得分:0)
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可以是任何类