12

私はこれまでにこのような質問を投稿したことがないので、SO にふさわしくない場合は、私の気持ちをあまり傷つけないでください。削除します。

私が気にかけていることすべてをできるだけ左マージンに近づけるために、次のようなものを書きたいと思っています。

DataService1.DataEntities dataEntities = new(constructorArg1, ...)

もう 1 つの理由は、型が割り当ての右側に既に存在する場合に var を使用することで得られる追加の画面領域が気に入っているからだと思いますが、私の脳は左側の型を探すのに何年も費やしています。繰り返しになりますが、自分のやり方に固執しているということは、仕様を望む正当な理由にはなりません...

4

6 に答える 6

25

C# 設計委員会は、このオブジェクト作成構文を検討したことがありますか?

はい、私たちは持っている。数年前に検討しました。この主張の証拠として、私の記事の最後の段落を参照してください。

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

設計チームのコンセンサスは、これは「あると便利な」機能であるが、機能の設計、実装、テスト、文書化、および保守にかなりのコストをかけるほど魅力的ではないというものでした。

また、リンク先のブログ エントリへのコメントは、この機能について非常に否定的です。多くの人が構文が魅力的でないと感じたようです。それはまた、機能を実行することに対するポイントでもありました。

ただし、提案された構文は、不変型の簡潔な宣言を促進する他の言語機能と組み合わせることができれば、特に優れたものになります。言語の仮想的な将来のバージョンでそのような機能を実行すると、提案する構文はより説得力のあるものになります。

さらに、私たちは一般に、「外側」から「内側」への推論を必要とする機能に抵抗することに注意してください。型情報が内側から外側に流れることを好みます。たとえば、次の問題を考えてみましょう。

M(new(blah));

M に 2 つのオーバーロードがあるとします。1 つは C を受け取り、もう 1 つは D を受け取ります。それは「新しい C(何とか)」または「新しい D(何とか)」ですか? どちらでもかまいません。ここで、両方を分析する必要があります。そして、両方が機能する場合は、どちらが優れているかを判断する必要があります.

ひどくなる。あなたが持っていると仮定します

M(new(new(blah)));

ここで、M は C と D を取り、C は E または F を取る 2 つのコンストラクターを持ち、D は G と H を取る 2 つのコンストラクターを持ちます。

M(new C(new E(blah)));
M(new C(new F(blah)));
M(new D(new G(blah)));
M(new D(new H(blah)));

選ばれていますが、その理由は?

外側から内側に推論すると、ネストの深さで分析するケースの数が O(c n ) になる「組み合わせ爆発」にすぐに陥ります。

C# はラムダに対してこの方法で推論を行います。これは、コンパイラーがパフォーマンスを向上させて正しくするのが最も難しい部分の 1 つです。同様の機能をコンストラクターに追加することに熱心ではありません。この構文を追加する場合、変数宣言または代入式の左側を分析することによって型が明確にわかっているシナリオに限定される可能性があります。

(いつものように、スケジュールや予算のない、発表されていない完全に架空の製品の架空の将来の言語機能に関するエリックの思索は、娯楽目的のためだけのものであり、特定の機能を備えた特定の将来の製品の約束として解釈されるべきではないことに注意してください設定。)

于 2011-04-25T16:52:20.987 に答える
2

タイプ名を繰り返さずに、保存に使用したメンバーと同じタイプのオブジェクトを作成したい場合は、「ストックトン新規」を使用できます。欠点は、初期化でメンバー名を繰り返す必要があることです。外観は次のとおりです。

class Program
    {
       private static T New<T>(out T item) where T : new()
       {
           item = new T();

           return item;
       }

       static Dictionary<Int32, Int32> _member = New(out _member);

       static void Main(string[] args)
       {
           Dictionary<Int32, Int32> local = New(out local);
       }
}

さらに、このメソッドを拡張して、いくつかの単純なオーバーロードを使用して、対応するインターフェイスの具象クラスを作成できます。

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item)
{
     item = new Dictionary<TKey, TValue>();

     return item;
}

public static IList<T> New<T>(out IList<T> item)
{
     item = new List<T>();

     return item;
}

今、あなたはこれを書くことができます:

IDictionary<Int32, Int32> local = New(out local);

嫌悪感、好奇心、または有用なテクニック?あなたが決める。

于 2011-04-25T18:37:21.327 に答える
2

左側から逆に式を推論します。そして、式が自明でない場合、それは非常に速く醜くなります。

ほとんどの場合(一部のラムダ型推論を除く)、式自体を見るだけで式が何をするかを理解できますが、それはあなたの構文では不可能です。ラムダではゲインが非常に大きいため、複雑な推論はラムダにとって良いトレードオフですが、そのような単純な機能にその複雑さを追加することは、単純な変数の初期化にとって悪いトレードオフです。

「右側の最も外側の式が式である変数への代入」という特殊なケースが考えられますnew。私には非常にエレガントに聞こえません。特にこのvar機能は、より柔軟でありながら、非常によく似たものをすでに実現しているためです。

于 2011-04-25T16:50:23.557 に答える
1

現在、この機能の正確な提案と実装があります。C# 8.0 で見られる可能性があります。

https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-new.mdを参照してください

于 2018-11-13T15:47:35.003 に答える
0

それについてはわかりませんが、物事を左に保ちたい場合は、代わりに次を使用できます。

var dataEntities = new DataService1.DataEntities(constructorArg1, ...)
于 2011-04-25T16:47:28.987 に答える
0

また、以下を持っているのはどうですか:

DataType dt;

以下と同じ意味:

DataType dt = new DataType();

その後:

DataType dt = { ParamOne = 1, ParamTwo = 2 };

以下と同じです:

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 };
于 2011-04-25T16:54:08.513 に答える