使用C#中的块等效?

Dan*_*ard 67 .net c# vb.net

我知道VB.Net,我正在努力搞清楚我的C#.在C#中是否有一个With块等价物?

谢谢

Jon*_*eet 55

虽然C#与一般情况没有任何直接等价,但C#3获取构造函数调用的对象初始化语法:

var foo = new Foo { Property1 = value1, Property2 = value2, etc };
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅深度C#的第8章 - 您可以从Manning的网站免费下载.

(免责声明 - 是的,将这本书交到更多人的手中符合我的利益.但是,嘿,这是一个免费章节,为您提供有关相关主题的更多信息......)

  • 这完全不同,因为这涉及创建类的实例,而 With 块则没有。 (2认同)
  • @JohnStock:因此“在一般情况下没有直接等价物”。但是,在仅使用`With`语句进行​​初始化的情况下,它仍然是相应的习惯用法。 (2认同)

Gul*_*zim 23

这就是Visual C#程序经理所说的: 为什么C#没有'with'语句?

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

  • 死链接.我认为这是它的新亮点:http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx (7认同)
  • 林克斯再次死了.这是来自C#FAQ的新内容:http://blogs.msdn.com/b/csharpfaq/archive/2004/03/11/why-doesn-tc-have-vb-net-s-with-operator.aspx (4认同)
  • 完全不同意。我无法在评论中格式化我想要的代码示例,但现在我有一个完整的“get”,里面堆满了“SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization”,而不是“With SKYLib.AccountsPayable.Client.ApiAuthorization”。授权 { .AuthToken = "123" .RefreshToken = "456" ... }`。 (3认同)
  • 除非您正在使用一个相当不寻常的库,否则没有理由不能缓存授权对象。`var auth = SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization; auth.AuthToken = "123"; auth.RefreshToken =“456”; ...`。换句话说,您的问题可以通过完全按照您所抱怨的答案所规定的方式来解决。 (2认同)

RTP*_*eat 21

正如上面链接的Visual C#程序管理器所说,在有些情况下,With语句更有效,这是他用作重复访问复杂表达式的简写时给出的示例.

使用扩展方法和泛型,您可以通过添加如下内容来创建与With语句模糊等效的内容:

    public static T With<T>(this T item, Action<T> action)
    {
        action(item);
        return item;
    }
Run Code Online (Sandbox Code Playgroud)

举一个如何使用它的简单例子,使用lambda语法然后你可以用它来改变这样的东西:

    updateRoleFamily.RoleFamilyDescription = roleFamilyDescription;
    updateRoleFamily.RoleFamilyCode = roleFamilyCode;
Run Code Online (Sandbox Code Playgroud)

对此:

    updateRoleFamily.With(rf =>
          {
              rf.RoleFamilyDescription = roleFamilyDescription;
              rf.RoleFamilyCode = roleFamilyCode;
          });
Run Code Online (Sandbox Code Playgroud)

在这样的示例中,唯一的优势可能是更好的布局,但是使用更复杂的引用和更多属性,它可以为您提供更易读的代码.

  • @DanAppleyard我把它看作封装,有时可能非常有用.但后来我有偏见,来自VB.NET,经常派上用场,我真的很想念C#.任何熟悉C#的人都没有可读性问题,只是让编码更容易一些,尤其是 处理长对象名称时. (4认同)
  • 我真的没有看到你的例子显示的优势.原始代码(pre-lambda)是[objectinstance].[property] = [value].lambda代码基本上只是用rf更改updateRoleFamily. (3认同)
  • 尝试使用更长的对象实例引用和更多属性.在上面的例子中,您将updateRoleFamily简化为rf并设置两个属性,这是正确的,并不是一个很大的好处.但是,如果您的对象实例类似于myDataStructure.GetButton(44),并且您必须设置十个属性,则可以使它更易于使用lambda或设置局部变量.就像最初的VB With声明一样,它只是一点点语法糖,你可以拿走或离开. (3认同)
  • 似乎设置局部变量会更有效且更易读。`var rf = myDataStructure.GetButton(44);`我根本看不到这是语法糖。这只是设置局部变量的复杂方法。*“只是因为您不能代表您应该这样做。” * (2认同)

Guu*_*ulh 13

不,那里没有.


Tim*_*ter 11

在" 使用对象 "部分的页面下方大约3/4 :

VB:

With hero 
  .Name = "SpamMan" 
  .PowerLevel = 3 
End With 
Run Code Online (Sandbox Code Playgroud)

C#:

//No "With" construct
hero.Name = "SpamMan"; 
hero.PowerLevel = 3; 
Run Code Online (Sandbox Code Playgroud)


Ben*_*har 8

withkeywork在C#版本9中引入!您可以使用它来创建对象的副本,如下所示

Person brother = person with { FirstName = "Paul" };
Run Code Online (Sandbox Code Playgroud)

“上面的行创建了一个新的 Person 记录,其中 LastName 属性是 person 的副本,FirstName 是“Paul”。您可以在 with 表达式中设置任意数量的属性。除了“clone”之外的任何合成成员方法可能由您编写。如果记录类型具有与任何合成方法的签名匹配的方法,则编译器不会合成该方法。”

更新:

在撰写此答案时,C#9 尚未正式发布,而只是预览版。但是,它计划在 2020 年 11 月与 .NET 5.0 一起发布

有关更多信息,请查看记录类型


Wou*_*hut 5

最简单的语法是:

{
    var where = new MyObject();
    where.property = "xxx";
    where.SomeFunction("yyy");
}

{
    var where = new MyObject();
    where.property = "zzz";
    where.SomeFunction("uuu");
}
Run Code Online (Sandbox Code Playgroud)

实际上,如果您想重用变量名,像这样的额外代码块非常方便。


Wal*_*hek 5

我所做的是使用 csharp ref 关键字。例如:

ref MySubClassType e = ref MyMainClass.MySubClass;
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这样的快捷方式: e.property而不是MyMainClass.MySubClass.property

  • 这称为 [ref locals](https://docs.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/ref-returns#ref-locals) 并在 C# 7.0 中引入。 (3认同)