2010-05-10 16 views
9

Ho avuto l'impressione che il compilatore C# digiti implicitamente un array basato su un tipo in cui possono essere tutti convertiti implicitamente.Tipizzazione implicita di array che implementano interfacce

il compilatore genera Nessun miglior tipo trovata per matrice implicitamente tipizzate

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

So che il modo per correggere questo è quello di dichiarare il tipo come:

new ISomething [] { obj1, ...} 

Ma io dopo un sotto le coperte scrivi aiuto qui.

+0

come il motivo per cui il compilatore non cerca di trovare un tipo di corrispondenza? –

risposta

14

Il compilatore C# considera l'insieme di tipi di tutti gli elementi specificati. Lo fa non considerano tipi di base comuni ecc

È potrebbe lanci una delle espressioni:

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

... ma personalmente mi basta usare la forma esplicita:

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

In alternativa, se si dichiarava espressamente uno o tutti i numeri obj1, obj2 e obj3 come tipo ISomething, ciò sarebbe funziona anche senza modificare l'espressione di inizializzazione dell'array.

Dal C# 3 spec, sezione 7.5.10.4:

Una creazione espressione array nella terza forma è indicato come un creazione matrice implicitamente tipizzato espressione. È simile al secondo modulo , tranne per il fatto che il tipo di array non è esplicitamente assegnato a , ma è determinato come il miglior tipo comune (§7.4.2.13) dell'insieme di espressioni nell'inizializzatore di array.

Sezione 7.4.2.13 si presenta così:

In alcuni casi, un tipo comune ha bisogno di essere dedotta per un insieme di espressioni. In particolare, i tipi di elementi di matrici tipizzate implicitamente e i tipi di restituzione di funzioni anonime con corpi di blocco vengono trovati in questo modo. Intuitivamente, dato un insieme di espressioni E1 ... Em questa inferenza dovrebbe essere equivalente a chiamare un metodo

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

con la Ei come argomenti.Più precisamente , l'inferenza inizia con un tipo unfixed variabile X. Tipo di uscita inferenze vengono quindi fatti da ogni Ei di tipo X. Infine, X è fisso e il tipo risultante S è il tipo comune risultante per la espressioni.

3

Se è possibile eseguire il cast delle istanze sul tipo di una qualsiasi istanza, verrà utilizzato tale tipo. Non è sufficiente che tutte le istanze abbiano alcun tipo in comune, altrimenti l'inizializzazione dell'array implicito avrebbe sempre successo e spesso genererebbe array indesiderati new object[].

0

come un lieve aggiunta alla risposta del Skeet:

è possibile lanciare uno degli elementi dell'array al tipo è necessario (interfaccia in questo caso) o se si ha solo un singolo elemento di questo tipo (non derivante ma di tipo diretto). Come ad esempio

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

questo funzionerà, ma pls non farlo :) Basta definire il tipo di matrice e cambiare il new[]-new IWindsorinstaller[]. È molto più leggibile se il tipo di array è definito in modo esplicito.

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

Nota: qui UIViewController può essere qualsiasi classe

Problemi correlati