2010-10-15 7 views
6

Para el # codificadores duro C aquí, esto podría parecer una pregunta completamente estúpido - sin embargo, me encontré con un fragmento de código de ejemplo en el foro AWS SDK y estaba completamente rozó por ella:Azúcar de sintaxis C#: ¿nueva forma de establecer los atributos del objeto?

RunInstancesRequest runInstance = new RunInstancesRequest() 
    .WithMinCount(1) 
    .WithMaxCount(1) 
    .WithImageId(GetXMLElement("ami")) 
    .WithInstanceType("t1.micro"); 

Este es muy reminiscente de la antigua sintaxis VB6 With ... End With, que lamentaba desde hace tiempo la ausencia de C#. Lo he compilado en mi proyecto VS2008 y funciona de maravilla, guardando numerosas líneas separadas que hacen referencia a estos atributos individualmente.

Estoy seguro de que he leído artículos en el pasado que explican por qué el -bloque de estilo VB6 With no estaba en C#, por lo que mi pregunta es: ¿tiene esta sintaxis siempre existió en el lenguaje, o es un cambio reciente de .NET que lo haya habilitado? ¿Podemos recubrir todas las instancias de objetos seguidas de cambios de atributos en el mismo azúcar?

+2

bien seguro, puede poner en práctica todos esos métodos si quieres Pero ¿por qué no usar la sintaxis del inicializador de objetos? –

+1

Respuestas excelentes aquí, pero solo puedo aceptar una, así que por ahora es la que se refiere específicamente a * Fluent Interfacing *, porque el ejemplo en el artículo deja muy claro lo que está sucediendo. Me siento un poco avergonzado de no haber hecho el enlace intuitivo, al ver que la línea en su totalidad tiene la forma 'A.B.C.D;', pero nunca antes había visto la técnica. Otra cuerda a la proa! :) –

Respuesta

16

Se implementan todos esos métodos, cada uno de los cuales también regresarán el objeto RunInstancesRequest (aka, this). Se llama Fluent Interface

+0

Buen enlace. Me gusta este ejemplo: http://en.wikipedia.org/wiki/Fluent_interface#C.23 –

4

No es azúcar sintáctica. Esos métodos simplemente establecen una propiedad y devuelven el objeto this.

0

Esta sintaxis siempre ha existido

25

¿No es esto mejor de todos modos?

RunInstancesRequest runInstance = new RunInstancesRequest 
{ 
    MinCount = 1, 
    MaxCount = 1, 
    ImageId = GetXMLEleemnt("ami"), 
    InstanceType = "t1.micro" 
}; 
+1

+1 Me encanta aprender cosas nuevas. – Brad

+0

Acepto, para establecer propiedades/constructores, esta es una sintaxis mejor. Pero en los escenarios en los que está trabajando con un elemento existente y con frecuencia modificará varias propiedades o llamará a varios métodos de una cadena, brillarán las interfaces fluidas. Es una de las muchas razones por las que jQuery es tan agradable de trabajar. – CaffGeek

+1

Y no puede usarlo en un objeto inmutable. Personalmente, creo que esta sintaxis solo debe usarse si el objeto original no se modifica (como en Linq). – CodesInChaos

1

La razón esta sintaxis funciona para RunInstancesRequest es que cada una de las llamadas a métodos que usted está haciendo volver la instancia original. El mismo concepto se puede aplicar a StringBuilder por la misma razón, pero no todas las clases tienen métodos implementados de esta manera.

3

Creo que esta técnica es diferente de la sintaxis With ... en VB. Creo que este es un ejemplo de encadenamiento. Cada método devuelve una instancia de sí mismo para que pueda encadenar las llamadas al método.

Ver Method-Chaining in C#

+0

+1 Las respuestas mejor calificadas no mencionan el encadenamiento. –

1

yo preferiría tener un constructor que toma todos esos valores de las propiedades como argumentos y los pone dentro de la clase.

+0

+1. No me agrada nada que permita que las clases parcialmente construidas vivan. Casi lo soporto para LINQ2SQL u otros ORM como un artefacto de la impedancia OO-ORM, pero no hay justificación la mayor parte del tiempo. No significa que no pueda usarse junto con los constructores apropiados y las invariantes de clase, pero puedo ver cómo esto alentaría la ruptura de eso. –

4
RunInstancesRequest runInstance = new RunInstancesRequest() 
.WithMinCount(1) 
.WithMaxCount(1) 
.WithImageId(GetXMLElement("ami")) 
.WithInstanceType("t1.micro"); 

==

RunInstancesRequest runInstance = new RunInstancesRequest().WithMinCount(1).WithMaxCount(1).WithImageId(GetXMLElement("ami")).WithInstanceType("t1.micro"); 

No sé si eso es considerado el azúcar sintáctica, o simplemente el formato puro.

+0

+1: el espacio en blanco alrededor del '.' es (y siempre ha sido) completamente ignorado por el compilador. –

1

Siempre ha existido en C# y de hecho en cualquier lenguaje orientado a objetos de estilo C (eh, el más popular lenguaje de estilo C, excepto C en sí!)

Es injusto compararlo con la sintaxis del VB6 With...End With, ya que es mucho más claro lo que está pasando en este caso (lo único bueno que tengo que decir sobre With...End With de VB6 es que al menos no es tan malo como los Javascripts ya que requiere puntos anteriores).

Es como se ha dicho, una combinación de la "interfaz fluida" y el hecho de que el operador . permite el espacio en blanco antes y después, para que podamos poner cada elemento en líneas nuevas.

StringBuilder es el caso más frecuente en C#, como en:

new StringBuilder("This") 
    .Append(' ') 
    .Append("will") 
    .Append(' ') 
    .Append("work") 
    .Append('.'); 

A relacionada, pero no del todo la misma, modelo es donde se encadenan los métodos de un objeto inmutable que devuelve un objeto diferente de del mismo tipo que en:

DateTime yearAndADay = DateTime.UtcNow.AddYears(1).AddDays(1); 

Sin embargo, otro está volviendo modificado IEnumerable<T> y IQueryable<T> objetos a partir de los métodos relacionados LINQ.

Aunque estos difieren en la devolución de diferentes objetos, en lugar de modificar un objeto mutable y devolver el mismo objeto.

Una de las razones principales por las que es más común en C++ y Java que en C# es que C# tiene propiedades. Esto hace que el medio más idiomático de asignar diferentes propiedades sea una llamada al establecedor relacionado que es sintácticamente lo mismo que establecer un campo. Sin embargo, bloquea mucho del uso más común de la lengua de interfaz fluida.

En lo personal, ya que el lenguaje interfaz fluida no está garantizada (no hay nada que decir MyClass.setProp(32) deberían volver this o, de hecho, que no debe volver 32 que también sería útil en algunos casos), y ya que no es tan idiomático en C#, prefiero evitarlo, aparte de con StringBuilder, que es un ejemplo tan bien saber que casi existe como un StringBuilder lenguaje independiente dentro de C#

Cuestiones relacionadas