visual versiones origin novedades language features evolution c# language-features

versiones - c# origin



¿Por qué no puedo hacer ??=en C#? (12)

Cuando lo pienso,

foo = foo ?? x

es realmente solo

foo = foo != null ? foo : x

y en ese punto, la analogía de + = comienza a desmoronarse.

A menudo me encuentro haciendo:

foo = foo ?? x;

¿Por qué no puedo hacer esto?

foo ??= x;

Editar : Sé que no es parte del idioma ... Mi pregunta es "¿por qué no?" Encuentro que la necesidad de repetir "foo" es desagradable y potencialmente propensa a errores. Se ve tan feo como:

foo = foo + x;


En general, el equipo de diseño del lenguaje C # es conservador en cuanto a agregar nueva sintaxis. Dicen que el valor de una adición al idioma debe sopesarse frente al costo de una mayor complejidad en el lenguaje.

Peter Hallam fue el líder en desarrollo de C # Compiler por un tiempo, y también miembro del equipo de diseño de lenguaje de C #. Escribió sobre su forma de medir una nueva característica, llamada Yardstick , aunque se centró más en las características de la GUI interactiva que en las características del lenguaje.

Este texto es particularmente relevante para la pregunta de ??= :

A menudo, la decisión de diseño correcta es no cambiar nada. Esta es probablemente la lección más importante que aprendí viendo a Anders en las reuniones de diseño del lenguaje C #. A menudo se plantea un área del lenguaje en la que se espera obtener algunos beneficios reales. Podríamos evitar que el usuario cometiera un error de codificación común, o podríamos mejorar la usabilidad del lenguaje para un cierto dominio problemático. Luego, después de pensar muy duro, a través de todas las opciones para abordar el problema, la respuesta es hacer ... ¡nada! Aunque el problema es válido, y parece que deberíamos poder agregar algo para mejorar la situación, después de una cuidadosa reflexión no hay forma de abordar el problema, que no cuesta más de lo que gana la solución. Muchas de las decisiones más importantes y valiosas que he visto hacer a Anders son las decisiones de no agregar complejidad al lenguaje a menos que el valor agregado justifique la complejidad. En los casos límite, casi nunca elige nada sobre agregar algo que es marginal.

Referencias


Ese estilo de afirmación se siente como una carga lenta de un comprador de propiedades. En ese caso, elegiría esta sintaxis

private Foo myFoo; public Foo MyFoo { get { return myFoo ?? (myFoo = new Foo()); } }


Hay una respuesta mucho más simple que todos faltan al discutir si la analogía de ??= a += tiene sentido.

Pregunta: ¿Por qué no puedes hacer foo ??= x; Cª#?

Respuesta: Debido a que cada característica comienza con menos 100 puntos , las características comienzan inexistentes y alguien tiene que hacer que sucedan y lo más probable es que si agregaron esa característica, esos recursos se gastaron en algo que tendría un mayor beneficio total para la base de clientes :

... piense todo el tiempo y el esfuerzo necesarios para diseñar cómo debería funcionar la característica, corte todas las condiciones de contorno, luego cámbiela, escriba pruebas automáticas para ella, ... escriba la documentación y el texto de ayuda, y continúe manteniendo el código, las pruebas y la documentación para la vida útil prevista de la característica (que en este caso probablemente sea para siempre). ¿Se podrían haber gastado todos esos recursos en algo que tendría un mayor beneficio total para la base de clientes? (La respuesta a eso es siempre "Sí"; todos y su cuñada pueden encontrar la forma de terminar la oración, "No puedo creer que hayan desperdiciado todo este tiempo en esta estúpida función en lugar de arreglar ..." )


No hay ninguna razón por la cual no podría existir tal operador, pero sospecho que la complejidad añadida del lenguaje, aunque leve, supera el beneficio (que yo consideraría "muy leve").

Básicamente, cualquier adición al idioma tiene una barra bastante alta para borrar. Usted dice que usa esto con bastante frecuencia, ¿con qué frecuencia? Mientras yo lo considero ?? a mano, no puedo decir que use incluso eso con mucha frecuencia.


No hay operador que realice esta operación. Sin embargo, es una sugerencia interesante para una versión futura del lenguaje. Sospecho que no se ha incluido hasta ahora porque el caso de uso principal para el operador coalescente, ?? , es con el tipo Nullable y obtiene el valor como en:

int? testValue; return testValue ?? 0;

En lugar de en operaciones de asignación como tu ejemplo. Además, mientras que += garantiza la modificación del valor de foo en todos los casos, pero += 0 , ??= no lo haría.


No veo muchas razones por las cuales usarías el ?? operador para autoasignar una variable.

Tal vez esté estableciendo foo según un valor de base de datos que pasa a ser NULL , por lo que tendría más sentido usar el ?? operador durante esa asignación (lo que elimina la necesidad de ?? =):

foo = (int?)rows["possiblyNullCount"] ?? 0;

Opuesto a:

foo = (int?)rows["possiblyNullCount"]; foo = foo ?? 0;


Porque no hay tal operador ?? = en C #.

Mientras que + = puede parecer dos operadores representados con sintaxis diferente, es solo un operador.


Principalmente porque + =, - = etc se añadieron más o menos como sugerencias para mantener la compatibilidad con C & C ++. (*) ¿Desde que? no es parte de C o C ++, no hubo necesidad de agregar el operador extra.

(*) Tenga en cuenta que en C ++, al definir operadores para una clase, uno normalmente define operador + = () y luego implementa operador + () basado en él. (Generalmente es la forma más eficiente). Sin embargo, en C #, uno implementa operator +, y el compilador automáticamente agrega operador + = basado en oper +. Esta es la razón por la que digo que los operadores + = tienen un añadido en el último momento.


Si bien no es exactamente lo que está pidiendo (no es ?? =) ... Tal vez podría aprovechar los métodos de extensión.

static void Main(string[] args) { object foo = null; object x = "something"; Console.WriteLine(foo.NullToValue(x)); } public static class ObjectExtensions { public static object NullToValue(this object obj, object value) { return obj != null ? obj : value; } }

No he dedicado una cantidad exhaustiva de tiempo a pensar en las posibles formas en que esto no funcionará, pero parece pasar la prueba del olor en mi aplicación de muestra ...


Yo también lo extraño - Ruby me ha arruinado. Aquí hay una construcción similar que puede usar en una expresión (si no es alérgico a los efectos secundarios):

foo ?? foo = x;

como en:

return foo ?? foo = x;

o (¡solo para ilustración!):

DoStuff( foo ?? foo = x );

Usar este patrón fuera del captador de propiedades probablemente no sea una gran idea.


?? no es un "operador" en el sentido de que realiza una "operación" con el valor de los operandos. Debería verlo solo como una construcción de lenguaje .

Supongamos que tienes:

node = node.next;

¿Te gustaría poder hacer lo siguiente?

node .= next;

Creo que ??= no existe por la misma razón que .= No existe.

Además, los operadores unarios como += , *= , etc. tienen contrapartes directas en el nivel de ensamblaje. Pseudoensamblaje:

add reg0, 1 mul reg1, 5

Es simplemente "natural" que existan estos operadores.