2010-05-10 25 views
9

J'avais l'impression que le compilateur C# taperait implicitement un tableau basé sur un type auquel ils pourraient tous être implicitement convertis.Typage implicite de tableaux implémentant des interfaces

Le compilateur génère Pas de meilleur type trouvé pour le tableau implicitement typé

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

Je sais que la façon d'y remédier est de déclarer le type comme:

new ISomething [] { obj1, ...} 

Mais je suis après un sous le type de couvertures aider ici.

+0

comme pourquoi le compilateur ne cherche pas à trouver un type de correspondance? –

Répondre

14

Le compilateur C# considère l'ensemble des types de tous les éléments spécifiés. Il ne pas considérer les types de base communs, etc.

Vous pourrait jeté l'une des expressions:

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

... mais personnellement, je venais d'utiliser la forme explicite:

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

Sinon, si vous déclarez explicitement tout ou partie de obj1, obj2 et obj3 que le type ISomething, ce serait fonctionne bien aussi sans changer l'expression d'initialisation de tableau.

De la spécification C# 3, section 7.5.10.4:

Une création tableau expression de la troisième forme est appelée une création de tableau typée implicitement expression. Il est similaire à la deuxième forme , sauf que le type élément du tableau n'est pas explicitement donné, mais déterminé comme le meilleur type commun (§7.4.2.13) de l'ensemble des expressions dans l'initialiseur de tableau.

Section 7.4.2.13 ressemble à ceci:

Dans certains cas, un type commun doit être inférés pour un ensemble d'expressions. En particulier, les types d'éléments de tableaux typés implicitement et les types de retour de de fonctions anonymes avec corps de bloc sont trouvés de cette manière. Intuitivement, étant donné un ensemble de expressions E1 ... Em cette inférence devrait être équivalent à appeler une méthode

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

avec l'Ei comme arguments.Plus précisément, l'inférence commence avec une variable de type non fixée X. inférences de type de sortie sont alors faites de chaque Ei de type X. Enfin, X est fixe et le type résultant S est le type commun résultant de la expressions.

3

Si les instances peuvent toutes être castées au type d'une instance, ce type sera utilisé. Il n'est pas suffisant que toutes les instances aient un type en commun, sinon l'initialisation du tableau implicite réussira toujours et génèrera souvent des tableaux new object[] non désirés.

0

En léger ajout à la réponse du Skeet:

Vous pouvez jeter l'un des éléments du tableau du type dont vous avez besoin (interface dans ce cas) ou si vous aviez un seul élément de ce type (ne dérive pas mais d'un type direct). Tels que

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

cela fonctionnera, mais pls ne pas faire ça :) définir exactement le type de tableau et changer le new[]-new IWindsorinstaller[]. Il est beaucoup plus lisible si le type de tableau est défini explicitement.

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

Note: ici UIViewController peut être une classe