Con bloque equivalente en C #?

Conozco a VB.Net y estoy tratando de mejorar mi C #. ¿Hay un bloque con equivalente en C #?

Gracias

Aunque C # no tiene ningún equivalente directo para el caso general, C # 3 gana la syntax del inicializador de objetos para llamadas de constructor:

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

Consulte el capítulo 8 de C # en profundidad para obtener más información: puede descargarlo gratis del sitio web de Manning .

(Descargo de responsabilidad: sí, me interesa que el libro entre en manos de más personas. Pero, oye, es un capítulo gratuito que brinda más información sobre un tema relacionado …)

Esto es lo que el gerente de progtwig de Visual C # tiene que decir: ¿Por qué C no tiene una statement ‘con’?

Muchas personas, incluidos los diseñadores del lenguaje C #, creen que “con” a menudo perjudica la legibilidad, y es más una maldición que una bendición. Es más claro declarar una variable local con un nombre significativo, y usar esa variable para realizar múltiples operaciones en un solo objeto, que tener un bloque con un tipo de contexto implícito.

Como dice el Administrador de progtwigs de Visual C # antes mencionado, hay situaciones limitadas en las que la sentencia With es más eficiente, el ejemplo que da cuando se usa como una abreviatura para acceder repetidamente a una expresión compleja.

Usando un método de extensión y generics, puede crear algo que sea vagamente equivalente a una statement With, agregando algo como esto:

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

Tomando un ejemplo simple de cómo podría usarse, usando la syntax lambda, puede usarlo para cambiar algo como esto:

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

A esto:

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

En un ejemplo como este, la única ventaja es quizás un diseño más agradable, pero con una referencia más compleja y más propiedades, podría darle un código más legible.

No no hay.

Aproximadamente 3/4 de la página en la sección ” Uso de objetos “:

VB:

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

DO#:

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

Podría usar el patrón del acumulador argumento.

Gran discusión sobre esto aquí:

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

La syntax más simple sería:

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

De hecho, los bloques de código adicionales son muy útiles si quieres reutilizar nombres de variables.

Algunas veces puedes salirte con la tuya haciendo lo siguiente:

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

(Ejemplo de código para EPPLus @ http://eszeumarmarototnet.blogspot.com)

Estaba usando de esta manera:

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

SetHeadFontStyle / SetHeadFillStyle es ExtMethod of Range como a continuación:

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

hacer alguna operación y devolver el Rango para la siguiente operación

se parece a Linq 🙂

pero ahora todavía no puede verse del todo: valor establecido de propiedad

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

Lo que hago es usar una palabra clave ref de csharp. Por ejemplo:

 ref MySubClassType e = ref MyMainClass.MySubClass; 

luego puede usar el atajo como: e.property lugar de MyMainClass.MySubClass.property

¡Un gran fan de With aquí!

Este es literalmente mi código actual de C #:

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

En VB podría ser:

 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 

Mucho más claro, creo. Incluso podría modificarlo para que sea más conciso ajustando la variable With . Y, en cuanto al estilo, ¡todavía tengo una elección ! Quizás algo que el Gerente del Progtwig C # haya pasado por alto.

Por otro lado, no es muy común ver esto, pero lo he usado en ocasiones:

En lugar de

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

Puedes usar

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

Se arriesga a una palmada en la muñeca, ¡como yo lo hago por publicar! - pero parece que obtienes todos los beneficios de una statement de Using en términos de eliminación, etc., sin el rigor extra.

NOTA: Esto puede salir mal ocasionalmente, por lo tanto, solo utilícelo para código no crítico. O no en absoluto. Recuerde: usted tiene una opción ...

Hay otra implementación interesante de with-pattern

 public static T With(this T o, params object[] pattern) => o; public static T To(this T o, out T x) => x = o; 

Puede navegar por más detalles mediante el enlace y buscar ejemplos de código en línea .

Variaciones de uso

 static Point Sample0() => new Point().To(out var p).With( pX = 123, pY = 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( pX = 123, pY = 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( pX = 123, pY = 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); } 

Si trabaja con estructuras [tipos de valor], el método de extensión similar también será útil

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

Puede aplicarse después del método With porque, por defecto, se devolverá la copia no modificada de struct

 struct Point { public double X; public double Y; public string Name; } static Point Sample0() => new Point().To(out var p).With( pX = 123, pY = 321, p.Name = "abc" ).Let(p); 

¡Disfrútalo si quieres!

Si hay varios niveles de objetos, puede obtener una funcionalidad similar con la directiva “using”:

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

hmm. Nunca he usado VB.net en profundidad, así que estoy haciendo una suposición aquí, pero creo que el bloque ‘usar’ podría estar cerca de lo que quieres.

using define un scope de bloque para una variable, ver el ejemplo a continuación

 using ( int temp = someFunction(param1) ) { temp++; // this works fine } temp++; // this blows up as temp is out of scope here and has been disposed 

Aquí hay un artículo de Microsoft que explica un poco más


EDITAR: sí, esta respuesta es incorrecta: la suposición original era incorrecta. El ‘CON’ de VB se parece más a los nuevos inicializadores de objetos C #:

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