2010-05-10 19 views
9

Ich hatte den Eindruck, dass der C# -Compiler implizit ein Array basierend auf einem Typ eingibt, in den alle implizit konvertiert werden können.Implizite Typisierung von Arrays, die Schnittstellen implementieren

Der Compiler erzeugt Nein für implizit typisierte Array gefunden beste Art

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 }; 
} 

Ich weiß, dass die Art und Weise, dies zu korrigieren ist die Art, wie zu erklären:

new ISomething [] { obj1, ...} 

Aber ich bin nach einem unter dem deckel type hilfe hier.

+0

wie in warum der Compiler versucht nicht, eine passende Art zu finden? –

Antwort

14

Der C# -Compiler berücksichtigt die Menge der Typen aller angegebenen Elemente. Es tut nicht betrachten gemeinsamen Grundtypen usw.

Sie konnte warf einer der Ausdrücke:

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

... aber ich persönlich würde benutzen Sie einfach die explizite Form:

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

Alternativ, wenn Sie explizit eine oder alle von obj1, obj2 und obj3 als Typ ISomething, das würde funktioniert auch ohne den Array-Initialisierungsausdruck zu ändern.

Vom # 3 spec C, Abschnitt 7.5.10.4:

Eine Array Schaffung Expression der dritten Form wird als ein implizit typisierten Array-Erstellung Ausdruck. Es ähnelt der zweiten Form , mit der Ausnahme, dass das Element Typ des Arrays nicht explizit gegeben, sondern als die beste gemeinsamen Typ (§7.4.2.13) des Satzes von Ausdrücke im Array Initialisierer bestimmt.

Abschnitt 7.4.2.13 sieht wie folgt aus:

In einigen Fällen eine häufige Art muss für eine Reihe von Ausdrücken abgeleitet werden. Insbesondere die Elementtypen von implizit typisierten Arrays und die Rückgabe Arten von anonymen Funktionen mit Block Körper sind auf diese Weise gefunden. Intuitiv gegeben eine Reihe von Ausdrücke E1 ... Em diese Folgerung sollte den Aufruf einer Methode

Tr M<X>(X x1 … X xm) 

mit dem Ei als Argumente entsprechen.Weitere gesagt, beginnt der Inferenz aus mit einer nicht fixierten Typ Variable X. Output Typinferenz gemacht werden dann von jedem Ei mit Typ X. Schließlich X festgelegt ist und die sich ergebende Form S ist die resultierende gemeinsame Typ für die Ausdrücke.

3

Wenn alle Instanzen in den Typ einer Instanz umgewandelt werden können, wird dieser Typ verwendet. Es ist nicht genug für alle Instanzen, irgendeinen Typ gemeinsam zu haben, sonst würde die Implicity-Array-Initialisierung immer erfolgreich sein und oft unerwünschte new object[] Arrays erzeugen.

0

Als leichtes Zusätzlich zu der Antwort der Skeet:

Sie können entweder gegossen eines der Array-Elemente an den Typ, den Sie (Schnittstelle in diesem Fall) benötigen oder wenn Sie nur ein einzelnes Element dieses Typs haben (nicht abgeleitet, sondern von einer direkten Art). Wie

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

dies funktionieren wird, aber pls tut nicht, dass :) einfach den Array-Typen definieren und die new[]-new IWindsorinstaller[] ändern. Es ist viel lesbarer, wenn der Array-Typ explizit definiert ist.

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 }; 

Hinweis: hier können UIViewController jede Klasse