2010-11-13 13 views
7

En Visual Basic, si se va a cambiar varias propiedades de un objeto único, hay una declaración With/End With:C# equivalente para la palabra clave de Visual Basic: 'Con' ... '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 

que sé C# puede hacerlo cuando se crea un nuevo objeto:

Object myObject = new Object { property1 = something, property2 = something2, ...}; 

¿Pero cómo lo hago si myOject ya está creado (como lo que está haciendo Visual Basic)?

+0

Unas cuantas personas están diciendo que es malo, pero me gustaría señalar que las convenciones de codificación de Microsoft para VB.NET dice que debe usar la palabra clave 'With' al hacer una serie de llamadas a un objeto - http://msdn.microsoft.com/en-us/library/h63fsef3.aspx –

Respuesta

11

No puede hacer esto en C#.

Esta característica es específica de VB y lo más cercano que puede venir en C# es el inicializador de objetos como usted describe.

3

si usted está tratando de evitar un montón de escribir se puede dar a su objeto un nombre más corto:

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

Sí, y para ir un paso más allá incluso puede hacer 'using (var x = myObject) {/ *newline*/x.property1=something;}' – Alxandr

+3

@Alxandr: Muy mala idea, que llamará a 'Dispose' al final del bloque (y no lo hará incluso compilar para tipos que no implementan 'IDispos capaz'). –

+0

Oo. Buen punto. Mi error. Solo pensé que descartaba la variable "x", pero ser una referencia podría ser fatal :-P – Alxandr

7

¿Qué tal esto?

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

¡Haz que sea un método de extensión! Luego puede hacer lo mismo con 'detailName.With (o => {o.Prop1 = 4})' – Alxandr

+2

Y por cierto. +1 para la creatividad :-) – Alxandr

+0

@Alxandr - Buena idea. – ChaosPandion

3

¿Por qué no tiene C# VB.NET de 'con' operador?

Muchas personas, incluidos los diseñadores de 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.

por @Jon Skeet

+6

... Y otras personas creen que la declaración "con" de VB es una característica útil que ofrece algunas semánticas que no se logran de la manera más conveniente a través de otros medios. – supercat

1

VB.NET incluye algunos de los defectos de diseño de VB6 en aras de la compatibilidad con versiones anteriores. Si bien Javascript tiene la misma falla de diseño (de hecho, una aún peor, ya que with conduce a construcciones más ambiguas), la mayoría de los demás lenguajes de sintaxis C no, por lo que no hay beneficio de compatibilidad con versiones anteriores al agregarlo a C#.

+0

En realidad, hay una clara ventaja de tener 'con' en JavaScript. ¡Le permite introducir un nuevo alcance a sus funciones! – ChaosPandion

+1

La declaración "Con" en VB, cuando se usa con estructuras, ofrece semántica que no está disponible convenientemente en C. Dado que el "Con" de VB utiliza un período principal para evitar la ambigüedad, no estoy seguro de por qué lo considera un diseño ¿falla? – supercat

0

Si la expresión "con" es un tipo de clase, la instrucción "Con" es equivalente a crear una nueva variable temporal de ese tipo, inicializada a la expresión "Con" y precediendo a cada una "." con esa variable. Si es un tipo de estructura, sin embargo, las cosas son más complicadas. Considere el código (obviamente no de la manera que normalmente cabría escribir algo, pero escrito como lo es para hacer un punto:.

 
    With MyPoints(N) ' Array of Point 
    N=SomeNewValue 
    .X = MyPoints(N).X 
    .Y = MyPoints(N).Y 
    End With 

La expresión "with" engancha efectivamente una referencia a MyPoints (N) Incluso si MyPoints es cambiado a alguna otra matriz, o se cambia N, la referencia retenida aún apuntará al mismo elemento de la misma matriz que cuando se ejecutó la instrucción With. Si se declara una variable local P de tipo Point y se agarraron MyPoints (N), y luego escribir en PX y PY, las escrituras solo llegarían a la copia local P, en lugar de actualizar la matriz. Para lograr una semántica similar en C#, uno tendría que usar variables locales para contener tanto MyPoints como N, o bien coloque el contenido de la instrucción With dentro de una función anónima que tenga un parámetro ref de tipo Point. Para evitar tener que crear un cierre en tiempo de ejecución, la función anónima también debe aceptar, probablemente por referencia, cualquier variable local que necesite del alcance externo.

0

@Mark Byers answer es bueno, pero la variable x vivirá después de establecer las propiedades. Y no puede usar el nombre x nuevamente (en el mismo bloque).

Prueba esto (Y objeto debe ser de tipo de referencia en esta muestra):

void Main() 
{ 
    var myObject1 = new Foo(); 
    var myObject2 = new Hoo(); 

    //elided... 

    { 
     var _ = myObject1; 
     _.MyPropertyA = 2; 
     _.MyPropertyB = "3"; 
    } 

    { 
     var _ = myObject2; 
     _.MyPropertyX = 5; 
     _.MyPropertyY = "asd"; 
    } 
} 
Cuestiones relacionadas