2016-04-14 1 views
-1

Comment initialiser automatiquement le type d'une méthode en C#?Création automatique du type de méthode

Par exemple,

List<int> MyIntList() 
{ 
    List<int> returnList = new List<int>(); 
    return returnList; 
} 

J'ai essentiellement créé une instance du type de retour, pour revenir. Y at-il quelque chose dans le langage C# qui infère le type de retour, de sorte qu'une instance ne doit pas être créé dans la méthode, comme:

List<int> MyIntList() 
{ 
    // invalid - "this" refers to the containing class, 
    // but looking for something that refers to the containing method. 
    this = new List<int>(); 
    return this; 
} 

Plus simplement, puis-je empêcher List<int> dans l'exemple de être tapé plus d'une fois, et laisser le compilateur déduire le reste?

+0

J'utilise 'List ' à titre d'exemple - la question est valable pour tout type, générique ou non. –

+5

Cela semble être une question X-Y. Pourquoi veux-tu faire cela? Quelle est l'utilisation prévue? –

+0

Que faire si le type de retour de la méthode était une classe abstraite? –

Répondre

1

Vous cherchez quelque chose comme

auto MyIntList() 
{ 
    return new List<int>(); 
} 

Avoir le compilateur déduire la valeur de retour et remplacer auto avec List<int>

Ce n'est pas possible avec la dernière version de C# (6.0)

+0

C'est exactement ce dont je parle. Je vous remercie. –

+0

Intéressant, y a-t-il une référence à 'auto'? Je ne peux pas en trouver un (seulement pour 'C++'). Cela ressemble à une bonne chose pour un programmeur paresseux, similaire à 'var'. – Sinatr

+0

'auto' n'existe pas pour C#. J'ai utilisé le mot 'auto' afin de ne pas confondre avec d'autres mots-clés C# existants. 'C++ 14' peut déduire le type de retour en utilisant le mot-clé' auto'. –

4

Si je vous comprends bien vous dire quelque chose comme ceci:

List<int> MyIntList() 
{ 
    var result = new List<int>(); 
    return result; 
} 

var est juste un espace réservé pour le type réel List<int> ou tout ce que vous lui attribuez. Contrairement à JavaScript en C#, le mot-clé se rapporte à un type fort, donc vous pouvez le traiter comme n'importe quel autre type, il liste automatiquement les membres appropriés pour ce type.

EDIT: Pour répondre à pourquoi vous ne pouvez pas faire ce que vous voulez: La signature de méthode indique souvent qu'une interface est renvoyée, mais le type réel doesnt question à tous. En général, vous ne le ferai pas de soins si la méthode retourne en fait un List, un Dictionary ou toute autre chose aussi longtemps qu'il met en œuvre IEnumerable par exemple. Cependant, si vous forcez le compilateur à retourner un List<int> au lieu d'un IEnumerable<int> par exemple, vous perdez tous les avantages des interfaces car vous en déduisez toujours le type réel de l'interface. Cela dit, le consommateur de la méthode pourrait même ajouter ou supprimer des éléments de/à la liste renvoyée. Si vous utilisez l'interface mentionnée, tout ce que vous renvoyez est quelque chose qui représente une liste de valeurs qui peuvent être énumérées.

Voir également ce cas:

List<int> MyIntList() 
{ 
    if (anyCondition) 
    { 
     var result = new List<int>(); 
     return result; 
    } 
    else 
    { 
     var result = new int[0]; 
     return result 
    } 
} 

Quel type devrait le déduire du compilateur dans ce cas? La signature de la méthode est un contrat à l'extérieur qui détermine les choses que vous pouvez faire avec le résultat.

+0

Ah, bien sûr. Oui, ça aide. Mais je me demande s'il existe une référence à la méthode contenant? –

+0

Pourquoi devriez-vous en avoir besoin? Vous avez une valeur que vous voulez retourner. Cela n'implique-t-il pas automatiquement une logique en deux étapes, d'abord obtenir la valeur, ensuite la renvoyer? – HimBromBeere

+0

la question concerne la syntaxe attendue par le compilateur. Regardez combien de fois la liste est répétée dans l'exemple fourni par cette réponse. Pourquoi ne pas simplement spécifier une fois, et être fait? –

4

Peut-être ceci:

private static T GetSomething<T>() where T: new() 
{ 
    return new T(); 
} 

Mais alors vous devrez passer le type comme typeparameter T:

var x = GetSomething<List<int>>(); 
0

Je ne peux pas donner une réponse précise quant à savoir si la spécification C#, mais je n'autorise peut fournir des exemples. D'abord, que faire si vous voulez une méthode pour retourner une interface? Dans vos exemples vous avez utilisé List<int> mais que faire si vous l'avez changé en IList<int>?Ou considérez cet exemple simplifié:

public interface IFoo 
{ 
    void Bar(); 
} 
public class Foo1 : IFoo 
{ 
    public Foo1() { } 
    public void Bar() => Console.WriteLine("Foo1.Bar"); 
} 
public class Foo2 : IFoo 
{ 
    private Foo2() { } 
    public static Foo2 Create => new Foo2(); 
    public void Bar() => Console.WriteLine("Foo2.Bar"); 
} 

Vous ne pouvez pas créer une instance d'une interface. Donc, cela est faux:

public IFoo BadFooCreate() => new IFoo(); // won't compile 

Mais cela fonctionnerait, mais on peut se poser la question de savoir comment le compilateur sais que vous voulez Foo1 être le IFoo particulier qui est retourné:

public IFoo GoodFooCreate() => new Foo1(); // compiles okay 

Cela fonctionne aussi:

public IFoo GoodFooCreate() => Foo2.Create(); // compiles okay 

Mais depuis foo2 a un constructeur privé, cela ne fonctionne pas:

public IFoo BadFoo2Create() => new Foo2(); // won't compile 

Un autre ensemble d'exemples tourne autour des classes abstraites. Tenir compte:

public abstract class Animal 
{ 
    public Animal() { } 
    public virtual string Name => "Generic Animal"; 
    public abstract string Speak(); 
} 
public class Dog : Animal 
{ 
    public override string Name => "Dog"; 
    public override string Speak() => "Bark"; 
} 
public class Cat : Animal 
{ 
    public override string Name => "Cat"; 
    public override string Speak() => "Meow"; 
} 

Ce serait une erreur parce que vous ne pouvez pas créer une instance d'une classe abstraite:

public Animal BadAnimalCreate() => new Animal(); // won't compile 

mais cela fonctionne parfaitement bien:

public Animal GoodAnimalCreate() => new Dog(); // compiles okay 

bien qu'encore une fois si la compilateur devaient créer automatiquement un type pour un programmeur paresseux, comment le compilateur sait-il utiliser Dog() et pas Cat()? Laisser le compilateur choisir en votre nom empiète sur la violation du Principle of Least Astonishment. Il y a de la paresse et ensuite on abdique votre responsabilité.