Visual Basic关键字的C#等价物:'With'...'End With'?

时间:2010-11-13 21:20:06

标签: c# vb.net language-design with-statement

在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 个答案:

答案 0 :(得分:11)

您无法在C#中执行此操作。

此功能特定于VB,而您最接近C#的是您描述的对象初始值设定项。

答案 1 :(得分:6)

这个怎么样?

static class Extension
{
    public static void With<T>(this T obj, Action<T> 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;
        });
    }
}

答案 2 :(得分:3)

如果您试图避免大量输入,可以为对象指定一个较短的名称:

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

答案 3 :(得分:3)

  

为什么C#没有VB.NET的'with'运算符?

     

许多人,包括C#语言设计师,都认为'with'经常损害可读性,而且更多的是诅咒而不是祝福。声明具有有意义名称的局部变量并使用该变量对单个对象执行多个操作比使用具有某种隐式上下文的块更清楚。

     

@Jon Skeet

答案 4 :(得分:1)

为了向后兼容,VB.NET包含了一些VB6的设计缺陷。虽然Javascript具有相同的设计缺陷(实际上更糟糕的是,因为它的with会导致更加模糊的构造),但大多数其他C语法语言都没有,因此将它添加到C#时没有向后兼容性的好处

答案 5 :(得分: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#中实现类似的语义,必须使用局部变量来保存MyPoints和N,或者将With语句的内容放在具有Point类型的ref参数的匿名函数中。为了避免在运行时创建闭包,匿名函数也应该接受(可能通过引用)从外部作用域中需要的任何局部变量。

答案 6 :(得分: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";
    }
}