【问题标题】:Implicit typing of arrays that implement interfaces实现接口的数组的隐式类型
【发布时间】:2010-05-10 01:40:30
【问题描述】:

我的印象是,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# implicit-typing


【解决方案1】:

C# 编译器会考虑所有指定元素的类型集。它确实考虑常见的基本类型等。

可以使用以下表达式之一:

var objects= new [] { obj1, obj2, (ISomething) obj3 };

...但我个人只会使用显式形式:

var objects= new ISomething[] { obj1, obj2, obj3 };

或者,如果您将obj1obj2obj3 中的任何一个或全部显式声明为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 的 Ei。最后,X 是固定的,结果类型 S 是 生成的通用类型 表达式。

【讨论】:

    【解决方案2】:

    如果所有实例都可以转换为任何一个实例的类型,则将使用该类型。让所有实例具有任何共同类型是不够的,否则隐式数组初始化总是会成功并经常生成不需要的 new object[] 数组。

    【讨论】:

      【解决方案3】:

      作为飞碟回复的一个小补充:

      您可以将其中一个数组项转换为您需要的类型(在本例中为接口),或者如果您只有一个该类型的元素(不是派生,而是直接类型)。比如

      public static IWindsorInstaller[] MobileRestComponentInstallers
              {
                  get
                  {
                      return new []
                                 {
                                       new RepositoryInstaller(),
                                       new AppSettingsInstaller(),
                                       // tens of other installers...
                                       GetLoggerInstaller() // public IWindsorInstaller GetLoggerInstaller()...
                                 };
                  }
              }
      

      这会起作用,但请不要这样做:) 只需定义数组类型并将new[] 更改为new IWindsorinstaller[]。 显式定义数组类型更具可读性。

      【讨论】:

        【解决方案4】:
        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 可以是任何类

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-09
          • 1970-01-01
          • 2019-03-22
          • 1970-01-01
          • 2010-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多