2009-03-26 9 views
3

Quelle valeur pensez-vous que les paramètres nommés et par défaut ajouteront dans C# .Net 4.0?C# .Net 4.0 Paramètres nommés et par défaut

Quelle serait une bonne utilisation pour ceux-ci (ce qui n'a pas déjà été réalisé avec la surcharge et le dépassement)?

Répondre

4

Il peut faire plus simple des constructeurs, en particulier pour les types immuables (qui sont importants pour le filetage) - see here for a full discussion. Pas aussi beau que devrait être peut-être, mais plus agréable que d'avoir beaucoup de surcharges. Vous pouvez évidemment pas utiliser initialiseurs d'objets avec des objets immuables, de sorte que l'habituel:

new Foo {Id = 25, Name = "Fred"} 

ne sont pas disponibles; Je me contenterai pour:

new Foo (Id: 25, Name: "Fred") 

Cela peut être étendue à l'idée générale de simplificatrices surcharge, mais dans la plupart cas, je préfère les surcharges qui annoncent des combinaisons juridiques. Les constructeurs sont un peu différents, IMO, puisque vous ne définissez (typiquement) que l'état initial. Le côté COM des choses est également important pour beaucoup de gens, mais je n'utilise pas beaucoup d'interopérabilité COM - donc ce n'est pas comme important pour moi.


Modifier les commentaires; Pourquoi n'ont-ils pas simplement utilisé la même syntaxe que les attributs d'utilisation? Simple - il peut être ambigu avec les autres membres/variables (qui ne sont pas un problème avec les attributs); prenons l'exemple:

[XmlElement("foo", Namespace = "bar")] 

qui utilise un paramètre régulier (pour le ctor, "foo"), et une assignation nommée. Supposons donc nous utilisons pour cela des arguments réguliers nommés:

SomeMethod("foo", SecondArg = "bar"); 

(qui pourrait aussi être un constructeur, je l'ai utilisé une méthode pour simplifier) ​​

Maintenant ... si nous avons une variable ou un propriété appelée SecondArg? Cela serait ambigu entre l'utilisation de SecondArg en tant qu'argument nommé SomeMethod et en assignant "bar" à SecondArg, et en passant "bar" comme argument normal.

Pour illustrer, ce qui est légal en C# 3.0:

static void SomeMethod(string x, string y) { } 
    static void Main() 
    { 
     string SecondArg; 
     SomeMethod("foo", SecondArg = "bar"); 
    } 

De toute évidence, SecondArg pourrait être une propriété, terrain, Varialble, etc ...

La syntaxe alternative ne pas cette ambiguïté .


Modifier - cette section par 280Z28: Désolé pour ajouter ceci ici, mais ce n'est pas vraiment une réponse unique et il est trop long pour les commentaires et inclut le code. Vous avez fait allusion à l'ambiguïté mais votre exemple n'a pas mis en évidence le cas décisif. Je pense que l'exemple que vous avez donné fait ressortir quelque chose qui pourrait prêter à confusion, mais les initialiseurs d'objet autour de {} empêchent une ambiguïté syntaxique sous-jacente. Mon explication pour le code suivant est incorporée en tant que commentaire de bloc multiligne.

[AttributeUsage(AttributeTargets.Class)] 
public sealed class SomeAttribute : Attribute 
{ 
    public SomeAttribute() { } 

    public SomeAttribute(int SomeVariable) 
    { 
     this.SomeVariable = SomeVariable; 
    } 

    public int SomeVariable 
    { 
     get; 
     set; 
    } 
} 

/* Here's the true ambiguity: When you add an attribute, and only in this case 
* there would be no way without a new syntax to use named arguments with attributes. 
* This is a particular problem because attributes are a prime candidate for 
* constructor simplification for immutable data types. 
*/ 

// This calls the constructor with 1 arg 
[Some(SomeVariable: 3)] 
// This calls the constructor with 0 args, followed by setting a property 
[Some(SomeVariable = 3)] 
public class SomeClass 
{ 
} 

+0

Ooh, très bien. Je pensais qu'ils devraient permettre à readonlys d'être assignés à partir des blocs d'initialisation, mais cette idée devient désordonnée très rapidement. Ceci est vraiment mieux. –

+0

Bien que comme vous le dites, ce serait bien si le constructeur est apparu par magie. –

+0

Je suis curieux de savoir pourquoi ils n'ont pas emprunté la syntaxe des arguments nommés utilisée par les attributs. –

0

Cela rendra l'interopérabilité COM beaucoup plus facile.

Jusqu'à C# 4 VB.Net était un langage beaucoup mieux pour interop. Sans valeurs par défaut, vous avez des listes massives de paramètres de référence factices en C#.

+0

Est-ce vraiment une bonne chose :) – Kibbee

+0

Oui - jusqu'à ce que la grande MS mordre la balle et produire un réel OS géré (que je ne peux pas les voir faire bientôt) certaines applications vont devoir faire face à des appels non gérés. – Keith

0

La brièveté du code est la plus évidente qui vient à l'esprit. Pourquoi définir plusieurs surcharges lorsque vous pouvez définir une fonction. Cependant, si vous avez deux paramètres de type identique, il n'est pas toujours possible de construire l'ensemble des surcharges dont vous pourriez avoir besoin.

1

Il vous aidera à esquiver le problème de fournir une API décente pour travailler avec des applications de bureau! :)

Certaines parties de l'API Office sont correctes, mais certains cas de bordure ont été clairement conçus pour être utilisés dans une langue avec des paramètres optionnels/nommés. C'est pourquoi C# doit les avoir.

+0

C'est un peu ce que j'ai dit;) Lorsque vous travaillez avec l'API Office VB.Net est miles plus facile à travailler que C# – Keith

1

Les paramètres facultatifs évitent également le problème où les classes fournissent des dizaines de méthodes qui ne sont que des variations sur les arguments acceptés.

Considérons la classe Exception. Au lieu d'un constructeur avec des arguments optionnels, il a quatre constructeurs pour chaque combinaison de 'has message', et 'has internal exception'. Tout va bien, mais maintenant considérez ce qui se passe si vous fournissez une valeur nulle à un constructeur prenant une innerException? Est-ce qu'il agit exactement comme le constructeur avec sans paramètre innerException, sortof comme le constructeur sans paramètre innerException, ou lance-t-il une exception de référence nulle? Un constructeur unique avec 2 paramètres optionnels aurait rendu plus évident que passer une null innerException était équivalent à ne pas l'inclure du tout. Un endroit parfait pour les arguments par défaut.

De même, n'oubliez pas que chaque classe Exception dérivée doit maintenant inclure 4 constructeurs, ce qui est un problème inutile.

0

Aussi cela ne compile pas:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] 
sealed class MyAttribute : Attribute 
{ 
    public MyAttribute(object a = null) 
    { 

    } 
} 


class Test 
{ 
    [My] // [My(a: "asd")] 
    int prop1 { get; set; } 
} 

alors que ce fait:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] 
sealed class MyAttribute : Attribute 
{ 
    public MyAttribute() 
    { 

    } 

    public object a { get; set; } 
} 

class Test 
{ 
    [My] // [My(a=null)] 
    int prop1 { get; set; } 
} 
Questions connexes