2009-03-26 4 views
3

C#.Net 4.0では、名前付きパラメータとデフォルトパラメータの値はどのくらいの価値があると思いますか?C#.Net 4.0名前付きデフォルトパラメータ

(これらは、オーバーロードとオーバーライドではまだ達成されていません)どのような用途に適していますか?

答えて

4

これはコンストラクタをより簡単にすることができます。特に、不変型(スレッド化にとって重要です)の場合は - see here for a full discussionです。 であるべきではありませんが、過負荷が多いよりも良いでしょう。あなたは明らかに不変オブジェクトを持つオブジェクトイニシャライザを使うことができないので、通常は

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

は利用できません。これは、オーバーロードを簡素化の一般的な考え方に拡張することができますが、ほとんどの例では、私は法的な組み合わせを宣伝オーバーロードを好む

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

:私はのために解決します。コンストラクターは少し違っていますが、あなたは初期状態を定義している(通常は)ので、IMOです。

多くの人にとってCOMの面も重要ですが、私は単純に多くのCOM相互運用機能を使用しません。したがって、これはとして、私にとって重要です。


コメントを編集:なぜ属性が使用するのと同じ構文を使用していないのですか?シンプル - 他のメンバー/変数と曖昧になることがあります(属性の問題ではありません)。

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

通常のパラメータ(ctor、 "foo")と名前付き割り当ての1つを使用します。だから我々は、通常の名前付き引数のためにこれを使用するとします。

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

(もコンストラクタすることができた。私は単純化のための方法を使用しました)私たちは、変数または持っている場合はどのような今

を...プロパティSecondArgと呼ばれる?これは、SecondArgSomeMethodの名前付き引数として使用し、に「bar」をSecondArgに割り当て、通常の引数として「bar」を渡すことで曖昧になります。説明するために

、これはC#3.0で有効です。

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

、SecondArgはなど、プロパティ、フィールド、varialble可能性が...

代替構文は、この曖昧さを持っていません。 。


編集 - このセクションは280Z28で編集できます:ここに追加することは申し訳ありませんが、本当にユニークな回答ではありません。あなたはあいまいさを暗示しましたが、あなたの例は決定的な事例を強調しませんでした。私はあなたが与えた例が混乱を招くかもしれない何かを指摘していると思いますが、オブジェクトイニシャライザの周りに必要な {}は根本的な構文的なあいまいさを防ぎます。次のコードの私の説明は、複数行のブロックコメントとして埋め込まれています。

[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

よ、とてもいいです。私は、読者がイニシャライザのブロックから割り当てられるようにしなければならないと考えていましたが、そのアイデアは非常に手早くなりました。これははるかに良いです。 –

+0

あなたが言うように、コンストラクターが魔法で登場すればいいでしょう。 –

+0

なぜ彼らが属性によって使用される名前付き引数構文を借りなかったのか不思議です。 –

0

これにより、COM相互運用性が大幅に向上します。

C#4まで、VB.Netはinteropの言語としてはるかに優れていました。デフォルトなしでは、C#に大量のダミー参照パラメータのリストがあります。

+0

は本当に良いことです:) – Kibbee

+0

はい - 大きなMSは弾丸をかむと実際の生産まで管理されたOS(私はすぐに彼らに会うことができません)いくつかのアプリケーションは、管理されていない呼び出しに対処する必要があるだろう。 – Keith

0

コードの簡潔さは、頭に浮かぶ明白なものです。 1つの関数を定義できるときに、いくつかのオーバーロードを定義するのはなぜですか?ただし、同じタイプのパラメータが2つある場合は、必要なオーバーロードの完全なセットを構築することが常に可能なわけではありません。

1

それはかわすにOfficeアプリケーションで動作するようにまともなAPIを提供する問題を助けます! :)

一部のOffice API部分は正常ですが、オプション/名前付きパラメータのある言語から使用するために明確に設計されたエッジケースがあります。だからこそ、C#はそれらを持つ必要があります。

+0

これはちょっと私が言ったことです;) Office API VB.Netで作業する場合、C# – Keith

1

オプションのパラメータは、クラスが受け入れられる引数のバリエーションだけである数十のメソッドを提供するという問題を回避します。

Exceptionクラスを検討してください。オプションの引数を持つ1つのコンストラクタの代わりに、 'has message'と 'inner exception'の組み合わせごとに4つのコンストラクタがあります。それは問題ありませんが、現在は、インナーExceptionをとるコンストラクタにnull値を指定するとどうなりますか?それは、innerExceptionパラメータを持たないコンストラクタと全く同じように動作しますか?それとも、innerExceptionパラメータを持たないコンストラクタのようなsortofか、またはnull参照例外をスローしますか?

オプションの2つのパラメータを持つ単一のコンストラクタでは、nullのinnerExceptionを渡すことは、それをまったく含まないことと同等であることが明らかになりました。デフォルトの引数のための完全な場所。

また、派生したすべてのExceptionクラスにも4つのコンストラクタが含まれていることを忘れないでください。これは無意味な面倒です。

0

また、これはコンパイルされません:

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

これがないながら:

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