8


1

Visual Basicキーワードと同等のC#: 'With' …​ 「で終わる」?

Visual Basicでは、単一のオブジェクトの複数のプロパティを変更する場合、「With / End With」ステートメントがあります。

Dim myObject as Object

// ' Rather than writing:
myObject.property1 = something
myObject.property2 = something2

// ' You can write:

with myObject
   .property1 = something
   .property2 = something2
   ...
End With

新しいオブジェクトを作成するときにC#でできることを知っています。

Object myObject = new Object { property1 = something, property2 = something2, ...};

しかし、 `myOject`が既に作成されている場合(Visual Basicの場合と同様)、どうすればよいですか?

7 Answer


11


  • C#ではこれを行えません。*

この機能はVBに固有であり、C#に最も近いのは、説明したようなオブジェクト初期化子です。


6


これはどう?

static class Extension
{
    public static void With(this T obj, Action a)
    {
        a(obj);
    }
}

class Program
{
    class Obj
    {
        public int Prop1 { get; set; }
        public int Prop2 { get; set; }
        public int Prop3 { get; set; }
        public int Prop4 { get; set; }
    }

    static void Main(string[] args)
    {
        var detailedName = new Obj();
        detailedName.With(o => {
            o.Prop1 = 1;
            o.Prop2 = 2;
            o.Prop3 = 3;
            o.Prop4 = 4;
        });
    }
}


3


多くの入力を避けたい場合は、オブジェクトに短い名前を付けることができます。

var x = myObject;
x.property1 = something;
x.property2 = something2;


3


_ _ * C#にVB.NETの「with」演算子がないのはなぜですか?*

C#言語設計者を含む多くの人々は、「with」は読みやすさを損なうことが多いと考えており、祝福よりも呪いのようなものです。 ローカル変数を意味のある名前で宣言し、その変数を使用して単一のオブジェクトに対して複数の操作を実行する方が、一種の暗黙のコンテキストを持つブロックを作成するよりも明確です。


1


VB.NETには、下位互換性のためにVB6の設計上の欠陥がいくつか含まれています。 Javascriptには同じ設計上の欠陥がありますが(「with」はより曖昧な構成要素につながるため、さらに悪いものです)、他のほとんどのC構文言語にはないため、C#に追加しても後方互換性の利点はありません。


0


「with」式がクラス型の場合、「With」ステートメントは、その型の新しい一時変数を作成し、「With」式に初期化し、各先頭の「。」の前に置きます。その変数で。 ただし、構造型の場合、事態はより複雑になります。 コードを考えてみてください(明らかに、通常は何かを書く方法ではありませんが、要点を述べるためにそのまま書きます:

  With MyPoints(N) ' Array of Point
    N=SomeNewValue
    .X = MyPoints(N).X
    .Y = MyPoints(N).Y
  End With

「With」ステートメントは、MyPoints(N)への参照を効果的にラッチします。 MyPointsが他の配列に変更された場合、またはNが変更された場合でも、ラッチされた参照は、Withステートメントが実行されたときと同じ配列の同じ要素を指します。 Point型のローカル変数Pを宣言してMyPoints(N)を取得し、P.XおよびP.Yに書き込むと、書き込みは配列を更新するのではなく、ローカルコピーPにのみヒットします。 C#で同様のセマンティクスを実現するには、ローカル変数を使用してMyPointとNの両方を保持するか、Point型のrefパラメーターを持つ匿名関数内にWithステートメントの内容を配置する必要があります。 実行時にクロージャを作成する必要を回避するために、匿名関数は、おそらく参照により、外部スコープから必要なローカル変数も受け入れる必要があります。


0


@Mark Byers answerは良いのですが、プロパティが設定された後、変数 `x`は存続します。 また、同じブロック内で名前「x」を再び使用することはできません。

これを試してください(このオブジェクトのオブジェクトは参照型でなければなりません):

void Main()
{
    var myObject1 = new Foo();
    var myObject2 = new Hoo();

    //elided...

    {
        var _ = myObject1;
        _.MyPropertyA = 2;
        _.MyPropertyB = "3";
    }

    {
        var _ = myObject2;
        _.MyPropertyX = 5;
        _.MyPropertyY = "asd";
    }
}