Cualquier producto o marco evoluciona. Principalmente se hace para satisfacer las necesidades de sus usuarios, aprovechar las nuevas capacidades informáticas y simplemente mejorarlo. A veces, el objetivo principal del diseño también cambia con el producto. C # o .net framework no es una excepción. Como vemos, la cuarta versión actual es muy diferente en comparación con la primera. Pero la cosa viene como una barrera para esta evolución: compatibilidad con versiones anteriores.
En la mayoría de los frameworks / productos, hay características que se habrían cortado si no hubiera necesidad de soportar la compatibilidad con versiones anteriores. Según usted, ¿cuáles son estas características en C # /. Net?
Por favor mencione una característica por respuesta.
fuente
Respuestas:
Métodos anónimos . Creo que todos están de acuerdo en que la sintaxis del método anónimo elegido para C # 2.0 es gruesa y torpe en comparación con la sintaxis lambda que agregamos a C # 3.0. Es profundamente desafortunado tener dos sintaxis casi idénticas para hacer lo mismo.
fuente
Me desharía de las colecciones no genéricas. Son una abominación ... y hay muchos casos en los que estoy usando linq y tengo que hacer algo como
Cada vez que tengo que hacer eso, una pequeña parte de mi alma muere.
fuente
nulo como un tipo . ¿Por qué demonios es "vacío" un tipo? No tiene instancias, no tiene valores, no puede usarlo como argumento de tipo genérico, tipo de parámetro formal, tipo local, tipo de campo o tipo de propiedad. No tiene significado como tipo; más bien, es un hecho sobre el efecto que tiene una llamada al método en la pila de la máquina virtual. Pero la máquina virtual es solo eso: una máquina virtual. ¡La máquina real pondrá el valor devuelto en un registro (típicamente EAX en x86) y no afectará en absoluto a la pila! El vacío como tipo es solo una mala idea en general.
Peor: cuando se usa en un tipo de puntero, ya
void*
que significa algo completamente diferente de lo que significa cuando se usa como tipo de retorno. Ahora significa "un puntero a una ubicación de almacenamiento de tipo desconocido", que no tiene nada que ver con su significado como "un método que no devuelve ningún valor".Podemos reemplazar
void*
como un tipo de puntero conIntPtr
. (Yvoid**
conIntPtr*
y así sucesivamente.) Podemos reemplazar el vacío como un tipo de retorno con "Unidad", un tipo que tiene un solo valor, es decir, nulo. Una implementación del CLR podría decidir que una llamada de función de tipo unidad podría optimizar su uso de registros o pilas de manera apropiada, sabiendo que el valor nulo que se está "devolviendo" puede ignorarse de manera segura.En un mundo así, ya no necesita separarse
Func<A, R>
yAction<T>
delegados.Action<T>
es justoFunc<T, Unit>
.fuente
Task
es solo unTask<Unit>
. Reimplementar los bits de la biblioteca del CTP asíncrono me hizo realmente desear esto ...La declaración vacía
;
. Propenso a errores, casi siempre es un error tipográfico, y no le da ningún significado adicional que no esté expresado por{}
.fuente
Covarianza insegura en matrices de tipo de referencia . Con la covarianza typesafe activada
IEnumerable<T>
, al menos parte de la necesidad de covarianza de matriz ha desaparecido. (Si tuviéramos una interfaz de lista de solo lectura covariante, entonces no la necesitaríamos en absoluto).fuente
IList<T>
heredaIReadableList<out T>
y no es genéricoIPemutable
, podría admitir cosas como la ordenación, pero las matrices lo admiten más fácilmente.El operador unario plus . El operador menos útil de todos los tiempos. Si no tuviéramos que guardarlo para compatibilidad con versiones anteriores, lo sacaría en un santiamén. ¿Quién usa esta cosa, alguien?
(Aclaración: el operador unario más
+x
no es el operador de preincremento++x
, ni el operador de postincremento ni el operador dex++
suma binariax+y
).fuente
+1 == 1
. Es bastante cerca de un no-op.if(a == +1 || a == -1){...}
.Los literales numéricos predeterminados a
double
Para la mayoría de los negocios aplicaciones ,
decimal
es más apropiado de todos modos ... o tal vez sería mejor simplemente eliminar la idea de un valor predeterminado y obligar al desarrollador a tomar la decisión.(Eso "eliminar el defecto" sería apropiado para algunas otras cosas, también. Por ejemplo, he renunciado a tratar de convencer a todo el mundo que las clases deben ser sellados por defecto, pero sospecho que es más fácil convencer a la gente que debe pensar acerca si su nueva clase debe sellarse o no, y hacerlo explícito).
fuente
Esta es más una guía que una característica, pero creo que es importante porque ya está demasiado arraigada en la mente de las personas como la mejor solución canónica:
El patrón oficial para implementar
IDisposable
.Es engorroso y hay mejores formas .
fuente
Yo sé que hay grandes diferencias entre las distintas clases de temporizador. ¿Pero no podríamos deshacernos de uno o dos de ellos?
fuente
Métodos y tipos de
Array
yList<T>
que se volvieron obsoletos con Linq, por ejemplo:Array.TrueForAll
puede ser reemplazado conEnumerable.All
Array.FindAll
puede ser reemplazado conEnumerable.Where
List<T>.ConvertAll
puede ser reemplazado conEnumerable.Select
Predicate<T>
puede ser reemplazado conFunc<T, bool>
Converter<T,R>
puede ser reemplazado conFunc<T, R>
IComparer<T>
realmente debería ser un delegadoFunc<T, T, int>
fuente
Predicate<T>
porque captura la intención de cómo se usa la función y ahorra un poco de tipeo.Delegados no genéricos Al igual que las colecciones no genéricas, los delegados no genéricos son inútiles ahora que tenemos las series Func y Action. Y habría cortado las variantes en tres parámetros. Si tiene más de tres parámetros, cree una estructura y úsela como parámetro único. Declarar un delegado específico para el manejo de eventos no es muy SECO.
fuente
Servicios web asmx
Creo que son bastante obsoletos con WCF hoy en día.
fuente
Winforms
Sería bueno no tener que navegar entre dos plataformas de escritorio. WPF es donde van las cosas, por lo que es frustrante tener una redundancia completa a nivel de plataforma.
fuente