【问题标题】:C# equivalent for Visual Basic keyword: 'With' ... 'End With'?Visual Basic 关键字的 C# 等效项:'With' ... 'End With'?
【发布时间】:2010-11-13 21:20:06
【问题描述】:

在 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 所做的那样),我该怎么做?

【问题讨论】:

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


【解决方案1】:

您不能在 C# 中执行此操作。

这个特性是 VB 特有的,在 C# 中最接近的就是你描述的对象初始化器。

【讨论】:

    【解决方案2】:

    这个怎么样?

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

    【讨论】:

    【解决方案3】:

    如果你想避免大量输入,你可以给你的对象一个更短的名字:

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

    【讨论】:

    • 是的,更进一步你甚至可以做到using(var x = myObject) {/*newline*/x.property1=something;}
    • @Alxandr:非常糟糕的主意,这将在块的末尾调用Dispose(甚至不会为不实现IDisposable 的类型编译)。
    • 哦。好点子。我的错。我只是认为它处理了“x”变量,但是作为参考可能是致命的:-P
    • 如果您希望变量在完成后超出范围,您可以将代码括在花括号中以创建新范围。
    • 避免大量打字,真的吗?有了我们拥有的超强智能?!这都是关于 imo 的可读性。
    【解决方案4】:

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

    包括 C# 语言设计者在内的许多人认为,“with”通常会损害可读性,并且与其说是祝福,不如说是诅咒。使用有意义的名称声明一个局部变量,并使用该变量对单个对象执行多个操作,比使用具有某种隐式上下文的块更清楚。

    @Jon Skeet

    【讨论】:

    • ...而且其他人认为 VB 的“with”语句是一个有用的功能,它提供了一些通过其他方式无法方便地实现的语义。
    • 有趣的是,他们称该语法为诅咒,然后几乎在对象初始化语法中复制了它...
    【解决方案5】:

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

    【讨论】:

    • 实际上,在 JavaScript 中使用 with 有一个明显的优势。它允许你为你的函数引入一个新的作用域!
    • VB 中的“With”语句与结构一起使用时,提供了 C 语言中不方便使用的语义。鉴于 VB 的“With”使用前导句点来避免歧义,我不确定为什么你认为这是一个设计缺陷?
    【解决方案6】:

    @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";
        }
    }
    

    【讨论】:

      【解决方案7】:

      如果“with”表达式是类类型,“With”语句相当于创建该类型的新临时变量,初始化为“With”表达式,并在每个前导“.”之前。与那个变量。但是,如果它是结构类型,则情况会更加复杂。考虑一下代码(显然不是通常写东西的方式,而是按原样写来说明一点:

      With MyPoints(N) ' 点数组 N=SomeNewValue .X = 我的积分(N).X .Y = 我的积分(N).Y 结束于

      “With”语句有效地锁定了对 MyPoints(N) 的引用。即使将 MyPoints 更改为其他数组,或者更改了 N,锁定的引用仍将指向同一数组的相同元素,就像执行 With 语句时所做的那样。如果声明一个 Point 类型的局部变量 P 并获取 MyPoints(N),然后写入 P.X 和 P.Y,则写入只会命中本地副本 P,而不是更新数组。为了在 C# 中实现类似的语义,必须使用局部变量来保存 MyPoints 和 N,或者将 With 语句的内容放在具有 Point 类型的 ref 参数的匿名函数中。为了避免在运行时创建闭包,匿名函数还应该接受(可能是通过引用)它需要来自外部作用域的任何局部变量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-07
        • 1970-01-01
        • 1970-01-01
        • 2013-04-16
        • 2012-04-18
        • 2011-05-12
        • 2018-04-14
        • 1970-01-01
        相关资源
        最近更新 更多