With block equivalent in C#?

C#.Netvb.net

C# Problem Overview


I know VB.Net and am trying to brush up on my C#. Is there a With block equivalent in C#?

C# Solutions


Solution 1 - C#

Although C# doesn't have any direct equivalent for the general case, C# 3 gain object initializer syntax for constructor calls:

var foo = new Foo { Property1 = value1, Property2 = value2, etc };

See chapter 8 of C# in Depth for more details - you can download it for free from Manning's web site.

(Disclaimer - yes, it's in my interest to get the book into more people's hands. But hey, it's a free chapter which gives you more information on a related topic...)

Solution 2 - C#

This is what Visual C# program manager has to say: Why doesn't C# have a 'with' statement?

> Many people, including the C# language designers, believe that 'with' > often harms readability, and is more of a curse than a blessing. It is > clearer to declare a local variable with a meaningful name, and use > that variable to perform multiple operations on a single object, than > it is to have a block with a sort of implicit context.

Solution 3 - C#

As the Visual C# Program Manager linked above says, there are limited situations where the With statement is more efficient, the example he gives when it is being used as a shorthand to repeatedly access a complex expression.

Using an extension method and generics you can create something that is vaguely equivalent to a With statement, by adding something like this:

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

Taking a simple example of how it could be used, using lambda syntax you can then use it to change something like this:

    updateRoleFamily.RoleFamilyDescription = roleFamilyDescription;
    updateRoleFamily.RoleFamilyCode = roleFamilyCode;

To this:

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

On an example like this, the only advantage is perhaps a nicer layout, but with a more complex reference and more properties, it could well give you more readable code.

Solution 4 - C#

About 3/4 down the page in the "Using Objects" section:

VB:

With hero 
  .Name = "SpamMan" 
  .PowerLevel = 3 
End With 

C#:

//No "With" construct
hero.Name = "SpamMan"; 
hero.PowerLevel = 3; 

Solution 5 - C#

No, there is not.

Solution 6 - C#

The with keywork is introduced in C# version 9! you can use it to create copy of object like follows

Person brother = person with { FirstName = "Paul" };

"The above line creates a new Person record where the LastName property is a copy of person, and the FirstName is "Paul". You can set any number of properties in a with-expression. Any of the synthesized members except the "clone" method may be written by you. If a record type has a method that matches the signature of any synthesized method, the compiler doesn't synthesize that method."

UPDATE:

At the time this answer is written, C#9 is not officially released but in preview only. However, it is planned to be shipped along with .NET 5.0 in November 2020

for more information, check the record types.

Solution 7 - C#

What I do is use a csharp ref keyword. For example:

ref MySubClassType e = ref MyMainClass.MySubClass;

you can then use the shortcut like: e.property instead of MyMainClass.MySubClass.property

Solution 8 - C#

Most simple syntax would be:

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

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

Actually extra code-blocks like that are very handy if you want to re-use variable names.

Solution 9 - C#

You could use the argument accumulator pattern.

Big discussion about this here:

http://blogs.msdn.com/csharpfaq/archive/2004/03/11/87817.aspx

Solution 10 - C#

Sometimes you can get away with doing the following:

var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(Color.Gray);
fill.PatternColor = Color.Black;
fill.Gradient = ...

(Code sample for EPPLus @ http://zeeshanumardotnet.blogspot.com)

Solution 11 - C#

I was using this way:

        worksheet.get_Range(11, 1, 11, 41)
            .SetHeadFontStyle()
            .SetHeadFillStyle(45)
            .SetBorders(
                XlBorderWeight.xlMedium
                , XlBorderWeight.xlThick
                , XlBorderWeight.xlMedium
                , XlBorderWeight.xlThick)
            ;

SetHeadFontStyle / SetHeadFillStyle is ExtMethod of Range like below:

 public static Range SetHeadFillStyle(this Range rng, int colorIndex)
 {
     //do some operation
     return rng;
 }

do some operation and return the Range for next operation

it's look like Linq :)

but now still can't fully look like it -- propery set value

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

Solution 12 - C#

A big fan of With here!

This is literally my current C# code:

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

In VB it could be:

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

Much clearer I think. You could even tweak it to be more concise by tuning the With variable. And, style-wise, I still have a choice! Perhaps something the C# Program Manager has overlooked.

As an aside, it's not very common to see this, but I have used it on occasion:

Instead of

Using oClient As HttpClient = New HttpClient
    With oClient
        .BaseAddress = New Uri("http://mysite")
        .Timeout = New TimeSpan(123)
        .PostAsync( ... )
    End With
End Using

You can use

With New HttpClient
    .BaseAddress = New Uri("http://mysite")
    .Timeout = New TimeSpan(123)
    .PostAsync( ... )
End With

You risk a wrist-slapping - as do I for posting! - but it seems that you get all the benefits of a Using statement in terms of disposal, etc without the extra rigmarole.

NOTE: This can go wrong occasionally, so only use it for non-critical code. Or not at all. Remember: You have a choice ...

Solution 13 - C#

To make life a little easier you can use vertical selection to quickly edit things

http://joelabrahamsson.com/select-columns-of-text-in-visual-studio/

Solution 14 - C#

There is another an interesting implementation of with-pattern

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;

You may browse more details by the link and research online code samples.

Variations of usage

static Point Sample0() => new Point().To(out var p).With(
	p.X = 123,
	p.Y = 321,
	p.Name = "abc"
);

public static Point GetPoint() => new Point { Name = "Point Name" };
static string NameProperty { get; set; }
static string NameField;

static void Sample1()
{
	string nameLocal;
	GetPoint().To(out var p).With(
		p.X = 123,
		p.Y = 321,
		p.Name.To(out var name), /* right side assignment to the new variable */
		p.Name.To(out nameLocal), /* right side assignment to the declared var */
		NameField = p.Name, /* left side assignment to the declared variable */
		NameProperty = p.Name /* left side assignment to the property */
	);
	
	Console.WriteLine(name);
	Console.WriteLine(nameLocal);
	Console.WriteLine(NameField);
	Console.WriteLine(NameProperty);
}

static void Sample2() /* non-null propogation sample */
{
	((Point)null).To(out var p)?.With(
		p.X = 123,
		p.Y = 321,
		p.Name.To(out var name)
	);
	
	Console.WriteLine("No exception");
}

static void Sample3() /* recursion */
{
	GetPerson().To(out var p).With(
		p.Name.To(out var name),
		p.Subperson.To(out var p0).With(
			p0.Name.To(out var subpersonName0)
		),
		p.GetSubperson().To(out var p1).With( /* method return */
			p1.Name.To(out var subpersonName1)
		)
	);
	
	Console.WriteLine(subpersonName0);
	Console.WriteLine(subpersonName1);
}

If you work with structs [value types] the similar extension method will be useful too

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

May be applied after With method because by default will be returned the unmodified copy of struct

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

Enjoy if you like!

Solution 15 - C#

I think the closets thing to "with" is static using, but only works with static's methods or properties. e.g.

using static System.Math;
...
public double Area
{
   get { return PI * Pow(Radius, 2); } // PI == System.Math.PI
}

More Info: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static

Solution 16 - C#

For me I was trying to auto generate code, and needed to reuse a simple variable like "x" for multiple different classes so that I didn't have to keep generating new variable names. I found that I could limit the scope of a variable and reuse it multiple times if I just put the code in a curly brace section {}.

See the example:

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

In VB I would have used the With and not needed variable "x" at all. Excluding the vb class definitions of Foo and Bar, the vb code is:

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

Solution 17 - C#

C# 9 and above:

The with keyword has finally been added!

It only supports record types.

Usage

The instance on the left hand side of the with keyword is copied and all of the mentioned fields on its right hand side are modified by their according value to return a new instance.

Example

Suppose we have the following record type:

public record Model(string Prefix, string Location, bool CoolLocation, bool HasCitizens);

And we have following original model initialized:

var model = new Model("Hello", "World", true, true);

We want to create a new model with all of the same fields except for Location and HasCitizens. We could do it in the following way:

var model2 = model with { Location = "Mars", HasCitizens = false };
   // Prefix = "Hello"
   // Location = "Mars"
   // CoolLocation = true
   // HasCitizens = false

C# 10 and above:

The with keyword can now additionally be used for struct and anonymous types.

More info to the with keyword can be found within the official docs

Solution 18 - C#

hmm. I have never used VB.net in any depth, so I'm making an assumption here, but I think the 'using' block might be close to what you want.

using defines a block scope for a variable, see the example below

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

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

Here is an article from Microsoft that explains a bit more


EDIT: yeah, this answer is wrong - the original assumption was incorrect. VB's 'WITH' is more like the new C# object initialisers:

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

Solution 19 - C#

If there are multiple levels of objects you can get similar functionality with the "using" directive:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDan AppleyardView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Gulzar NazimView Answer on Stackoverflow
Solution 3 - C#RTPeatView Answer on Stackoverflow
Solution 4 - C#Timothy CarterView Answer on Stackoverflow
Solution 5 - C#GuulhView Answer on Stackoverflow
Solution 6 - C#Benzara TaharView Answer on Stackoverflow
Solution 7 - C#Walter ZydhekView Answer on Stackoverflow
Solution 8 - C#Wouter SchutView Answer on Stackoverflow
Solution 9 - C#BBetancesView Answer on Stackoverflow
Solution 10 - C#SeanView Answer on Stackoverflow
Solution 11 - C#IlPADlIView Answer on Stackoverflow
Solution 12 - C#SteveCinqView Answer on Stackoverflow
Solution 13 - C#SidView Answer on Stackoverflow
Solution 14 - C#MakemanView Answer on Stackoverflow
Solution 15 - C#JaiderView Answer on Stackoverflow
Solution 16 - C#JroonkView Answer on Stackoverflow
Solution 17 - C#Despacito 2View Answer on Stackoverflow
Solution 18 - C#mlennoxView Answer on Stackoverflow
Solution 19 - C#BoloView Answer on Stackoverflow