在C#中具有块等效性?

在C#中具有块等效性?,c#,.net,vb.net,C#,.net,Vb.net,我了解VB.Net,正在努力复习我的C。在C#中是否有与块等效的块 谢谢不,没有。您可以使用参数累加器模式 关于这一点的大讨论如下: 嗯。我从未深入使用过VB.net,所以我在这里做一个假设,但我认为“使用”块可能接近您想要的 使用定义变量的块范围,请参见下面的示例 using ( int temp = someFunction(param1) ) { temp++; // this works fine } temp++; // this blows up as temp is ou

我了解VB.Net,正在努力复习我的C。在C#中是否有与块等效的块


谢谢

不,没有。

您可以使用参数累加器模式

关于这一点的大讨论如下:


嗯。我从未深入使用过VB.net,所以我在这里做一个假设,但我认为“使用”块可能接近您想要的

使用定义变量的块范围,请参见下面的示例

using ( int temp = someFunction(param1) ) {
   temp++;  // this works fine
}

temp++; // this blows up as temp is out of scope here and has been disposed


编辑:是的,这个答案是错误的——最初的假设是错误的。VB的“WITH”更像是新的C#对象初始化器:

var yourVariable = new yourObject { param1 = 20, param2 = "some string" };

大约3/4页下方的“”部分:

VB:

C#:

虽然C#在一般情况下没有任何直接等价物,但C#3为构造函数调用获得对象初始值设定项语法:

var foo = new Foo { Property1 = value1, Property2 = value2, etc };
有关更多详细信息,请参阅C#Depth的第8章-您可以从免费下载

(免责声明-是的,让更多人掌握这本书符合我的利益。但是,嘿,这是一个免费的章节,为您提供有关相关主题的更多信息…

这是Visual C#程序经理必须说的:

许多人,包括C语言设计师,相信“with” 通常会损害可读性,与其说是福,不如说是祸。它是 更清楚地声明具有有意义名称的局部变量,并使用 该变量用于对单个对象执行多个操作,而不是 它是一个具有某种隐式上下文的块

正如上面链接的Visual C#Program Manager所说,在有限的情况下,With语句的效率更高,他举了一个例子,当With语句被用作速记以重复访问复杂表达式时

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

    public static T With<T>(this T item, Action<T> action)
    {
        action(item);
        return item;
    }
为此:

    updateRoleFamily.With(rf =>
          {
              rf.RoleFamilyDescription = roleFamilyDescription;
              rf.RoleFamilyCode = roleFamilyCode;
          });

在这样一个示例中,唯一的优势可能是更好的布局,但如果有更复杂的引用和更多的属性,它很可能会为您提供更可读的代码。

有时您可以通过执行以下操作来避免:

var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(Color.Gray);
fill.PatternColor = Color.Black;
fill.Gradient = ...
(EPPLus@的代码示例)

我是这样使用的:

        worksheet.get_Range(11, 1, 11, 41)
            .SetHeadFontStyle()
            .SetHeadFillStyle(45)
            .SetBorders(
                XlBorderWeight.xlMedium
                , XlBorderWeight.xlThick
                , XlBorderWeight.xlMedium
                , XlBorderWeight.xlThick)
            ;
SetHeadFontStyle/SetHeadFillStyle是范围的ExtMethod,如下所示:

 public static Range SetHeadFillStyle(this Range rng, int colorIndex)
 {
     //do some operation
     return rng;
 }
执行一些操作并返回下一个操作的范围

它看起来像Linq:)

但现在仍然不能完全像它--属性集值

with cell.Border(xlEdgeTop)
   .LineStyle = xlContinuous
   .Weight = xlMedium
   .ColorIndex = xlAutomatic

最简单的语法是:

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

{
    var where = new MyObject();
    where.property = "zzz";
    where.SomeFunction("uuu");
}

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

如果存在多个级别的对象,您可以通过“使用”指令获得类似的功能:

using System;
using GenderType = Hero.GenderType; //This is the shorthand using directive
public partial class Test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var myHero = new Hero();
        myHero.Name = "SpamMan";
        myHero.PowerLevel = 3;
        myHero.Gender = GenderType.Male; //instead of myHero.Gender = Hero.GenderType.Male;
    }
}
public class Hero
{
    public enum GenderType
    {
        Male,
        Female,
        Other
    }
    public string Name;
    public int PowerLevel;
    public GenderType Gender;
}

还有另一个有趣的with模式实现

public static T With<T>(this T o, params object[] pattern) => o;
public static T To<T>(this T o, out T x) => x = o;
如果使用structs[value types],类似的扩展方法也会很有用

public static TR Let<T, TR>(this T o, TR y) => y;

尽情享受吧

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

ref MySubClassType e = ref MyMainClass.MySubClass;
然后可以使用快捷方式,如:
e.property
而不是
MyMainClass.MySubClass.property
这里是
的忠实粉丝

这就是我目前的C代码:

你可以用

With New HttpClient
    .BaseAddress = New Uri("http://mysite")
    .Timeout = New TimeSpan(123)
    .PostAsync( ... )
End With
你有被拍打手腕的危险-我发帖的时候也是但是,似乎在处置等方面使用
语句可以获得
的所有好处,而不需要额外的繁琐


注意:这可能会偶尔出错,因此仅对非关键代码使用它。或者根本没有。请记住:您有一个选择…

我认为“使用”的壁橱是
静态使用的,但只适用于静态的方法或属性。
e、 g

更多信息:

为了让生活更轻松,您可以使用垂直选择快速编辑内容


对我来说,我试图自动生成代码,需要为多个不同的类重用一个简单的变量,如“x”,这样我就不必不断生成新的变量名。我发现,如果我将代码放在大括号部分{},我可以限制变量的范围并多次重用它

请参见示例:

public class Main
{
    public void Execute()
    {
        // Execute new Foos and new Bars many times with same variable.
        double a = 0;
        double b = 0;
        double c = 0;
        double d = 0;
        double e = 0;
        double f = 0;

        double length = 0;
        double area = 0;
        double size = 0;

        {
            Foo x = new Foo(5, 6).Execute();
            a = x.A;
            b = x.B;
            c = x.C;
            d = x.D;
            e = x.E;
            f = x.F;
        }
        {
            Bar x = new Bar("red", "circle").Execute();
            length = x.Length;
            area = x.Area;
            size = x.Size;
        }
        {
            Foo x = new Foo(3, 10).Execute();
            a = x.A;
            b = x.B;
            c = x.C;
            d = x.D;
            e = x.E;
            f = x.F;
        }
        {
            Bar x = new Bar("blue", "square").Execute();
            length = x.Length;
            area = x.Area;
            size = x.Size;
        }
    }
}

public class Foo
{
    public int X { get; set; }
    public int Y { get; set; }
    public double A { get; private set; }
    public double B { get; private set; }
    public double C { get; private set; }
    public double D { get; private set; }
    public double E { get; private set; }
    public double F { get; private set; }

    public Foo(int x, int y)
    {
        X = x;
        Y = y;
    }

    public Foo Execute()
    {
        A = X * Y;
        B = X + Y;
        C = X / (X + Y + 1);
        D = Y / (X + Y + 1);
        E = (X + Y) / (X + Y + 1);
        F = (Y - X) / (X + Y + 1);
        return this;
    }
}

public class Bar
{
    public string Color { get; set; }
    public string Shape { get; set; }
    public double Size { get; private set; }
    public double Area { get; private set; }
    public double Length { get; private set; }
    
    public Bar(string color, string shape)
    {
        Color = color;
        Shape = shape;
    }

    public Bar Execute()
    {
        Length = Color.Length + Shape.Length;
        Area = Color.Length * Shape.Length;
        Size = Area * Length;
        return this;
    }
}
在VB中,我会使用With,而根本不需要变量“x”。不包括Foo和Bar的vb类定义,vb代码为:

Public Class Main
    Public Sub Execute()
        Dim a As Double = 0
        Dim b As Double = 0
        Dim c As Double = 0
        Dim d As Double = 0
        Dim e As Double = 0
        Dim f As Double = 0
        Dim length As Double = 0
        Dim area As Double = 0
        Dim size As Double = 0

        With New Foo(5, 6).Execute()
            a = .A
            b = .B
            c = .C
            d = .D
            e = .E
            f = .F
        End With

        With New Bar("red", "circle").Execute()
            length = .Length
            area = .Area
            size = .Size
        End With

        With New Foo(3, 10).Execute()
            a = .A
            b = .B
            c = .C
            d = .D
            e = .E
            f = .F
        End With

        With New Bar("blue", "square").Execute()
            length = .Length
            area = .Area
            size = .Size
        End With
    End Sub
End Class

C#version 9中引入了带有
键的
!
您可以使用它创建对象的副本,如下所示

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

更新:

在撰写此答案时,C#9尚未正式发布,只是在预览中发布。不过,它将于2020年11月与.NET 5.0一起发布


有关更多信息,请查看。

我知道这上面有一个副本,但就我的一生而言,我无法找到一个可以找到它的搜索查询。@ctacke:我想“不会那么难…”,然后花了10分钟试图找到它,但没有成功。…谷歌知道:“使用c#站点:stackoverflow.comgives:不,using语句是非常不同的-using语句的要点是在块的末尾处理资源。这并没有使引用值的时间缩短。谢谢Jon,学习另一门语言总是很好,我想我应该注意“假设使你和我变成一个傻瓜”这句老话,但我猜在这种情况下,只有我看起来很糟糕;)不。。。初始值设定项仅在初始化时起作用。。。看看流畅的界面吧!没有理由
使用
无法缩短引用值的时间(借用上面的答案):
使用(var c=cell.Border(xlEdgeT
struct Point
{
    public double X;
    public double Y;
    public string Name;
}

static Point Sample0() => new Point().To(out var p).With(
    p.X = 123,
    p.Y = 321,
    p.Name = "abc"
).Let(p);
ref MySubClassType e = ref MyMainClass.MySubClass;
if (SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.AccessTokenExpiry == null || SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.AccessTokenExpiry < DateTime.Now)
{
    SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.Refresh();
    _api = new SKYLib.AccountsPayable.Api.DefaultApi(new SKYLib.AccountsPayable.Client.Configuration { DefaultHeader = SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.ApiHeader });
}
With SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization
    If .AccessTokenExpiry Is Nothing OrElse .AccessTokenExpiry < Now Then .Refresh()
    _api = New SKYLib.AccountsPayable.Api.DefaultApi(New SKYLib.AccountsPayable.Client.Configuration With {DefaultHeader = .ApiHeaders}
End With
Using oClient As HttpClient = New HttpClient
    With oClient
        .BaseAddress = New Uri("http://mysite")
        .Timeout = New TimeSpan(123)
        .PostAsync( ... )
    End With
End Using
With New HttpClient
    .BaseAddress = New Uri("http://mysite")
    .Timeout = New TimeSpan(123)
    .PostAsync( ... )
End With
using static System.Math;
...
public double Area
{
   get { return PI * Pow(Radius, 2); } // PI == System.Math.PI
}
public class Main
{
    public void Execute()
    {
        // Execute new Foos and new Bars many times with same variable.
        double a = 0;
        double b = 0;
        double c = 0;
        double d = 0;
        double e = 0;
        double f = 0;

        double length = 0;
        double area = 0;
        double size = 0;

        {
            Foo x = new Foo(5, 6).Execute();
            a = x.A;
            b = x.B;
            c = x.C;
            d = x.D;
            e = x.E;
            f = x.F;
        }
        {
            Bar x = new Bar("red", "circle").Execute();
            length = x.Length;
            area = x.Area;
            size = x.Size;
        }
        {
            Foo x = new Foo(3, 10).Execute();
            a = x.A;
            b = x.B;
            c = x.C;
            d = x.D;
            e = x.E;
            f = x.F;
        }
        {
            Bar x = new Bar("blue", "square").Execute();
            length = x.Length;
            area = x.Area;
            size = x.Size;
        }
    }
}

public class Foo
{
    public int X { get; set; }
    public int Y { get; set; }
    public double A { get; private set; }
    public double B { get; private set; }
    public double C { get; private set; }
    public double D { get; private set; }
    public double E { get; private set; }
    public double F { get; private set; }

    public Foo(int x, int y)
    {
        X = x;
        Y = y;
    }

    public Foo Execute()
    {
        A = X * Y;
        B = X + Y;
        C = X / (X + Y + 1);
        D = Y / (X + Y + 1);
        E = (X + Y) / (X + Y + 1);
        F = (Y - X) / (X + Y + 1);
        return this;
    }
}

public class Bar
{
    public string Color { get; set; }
    public string Shape { get; set; }
    public double Size { get; private set; }
    public double Area { get; private set; }
    public double Length { get; private set; }
    
    public Bar(string color, string shape)
    {
        Color = color;
        Shape = shape;
    }

    public Bar Execute()
    {
        Length = Color.Length + Shape.Length;
        Area = Color.Length * Shape.Length;
        Size = Area * Length;
        return this;
    }
}
Public Class Main
    Public Sub Execute()
        Dim a As Double = 0
        Dim b As Double = 0
        Dim c As Double = 0
        Dim d As Double = 0
        Dim e As Double = 0
        Dim f As Double = 0
        Dim length As Double = 0
        Dim area As Double = 0
        Dim size As Double = 0

        With New Foo(5, 6).Execute()
            a = .A
            b = .B
            c = .C
            d = .D
            e = .E
            f = .F
        End With

        With New Bar("red", "circle").Execute()
            length = .Length
            area = .Area
            size = .Size
        End With

        With New Foo(3, 10).Execute()
            a = .A
            b = .B
            c = .C
            d = .D
            e = .E
            f = .F
        End With

        With New Bar("blue", "square").Execute()
            length = .Length
            area = .Area
            size = .Size
        End With
    End Sub
End Class