2009-03-13 10 views
7

Estaba lidiando con cadenas, y me molesta que las cadenas puedan ser anulables. Entonces, tengo que tener¿Qué decisión de lenguaje en C# te molesta?

if((teststring??string.Empty)==string.Empty) 

por todo el lugar. ¿Cadena? han sido tan difíciles de permitir la nulabilidad en los relativamente pocos casos en que se necesita (dbs, entradas de usuario idiotas, etc.). También me irrita tener que exportar interfaces de solo lectura en los casos en que deseo alguna forma de corrección const. Entonces, ¿qué construcción/decisión del lenguaje C# te molesta?

EDIT: Gracias por la función isnullorempty, ¡no había visto eso antes! Aún no disminuye mi molestia por que sea anulable: D

+10

o podría hacer si (string.IsNullOrEmpty (teststring)) ... –

+0

no sea tan ruidoso jjnguy. Es una pregunta divertida para un viernes y su programación relacionada. Además, no lloriquea, tengo curiosidad por lo que molesta a la gente. El hecho de que exista una isnullorempty no hace que la decisión de permitir cadenas con nulos sea menos molesta para mí. – Steve

+0

Vea también: http://stackoverflow.com/questions/411906/c-net-design-flaws/ –

Respuesta

21

Convertir cadenas en un tipo de referencia me parece del todo razonable.

Es una lástima que no se pueda declarar un tipo de variable/parámetro/devolución que sea que no se puede nulos, aunque - por ejemplo,

// Never returns null 
public string! Foo() 
{ 
} 

contratos de código en .NET 4.0 ayuden con esto, yo creo - pero es un poco tarde para que sea generalizado.

Hace un tiempo escribí un blog entry on the mistakes of C#. Para resumir que mensaje:

C# 1:

  • Falta de getter separada/acceso setter de propiedades.
  • Falta de genéricos. La vida habría sido mucho más dulce con los genéricos desde el principio.
  • Las clases no están selladas por defecto.
  • Enumerando solo números.
  • La secuencia de escape de caracteres "\ x".
  • Varias cosas acerca de la instrucción switch :)
  • reglas de resolución
  • Algunos de sobrecarga extraña
  • El "bloqueo" de palabras clave, en lugar de "utilizar" con una tocken bloqueo.

C# 2:

  • falta de métodos parciales (llegó en C# 3)
  • Falta de varianza genérica (que viene en C# 4)
  • La clase System.Nullable (no Nullable<T> - está bien!)
  • InternalsVisibleTo que requiere la clave pública completa para ensamblajes fuertemente firmados en lugar del token de clave pública.

C# 3:

  • La falta de apoyo a la inmutabilidad - un montón de cambios mejorada oportunidades para mutar tipos (propiedades automáticas, colección de objetos y Inicializadores) pero ninguno de ellos realmente funciona para tipos mutables
  • Extensión método de descubrimiento
+0

buena lista. Me gusta el enfoque histórico! – Steve

+0

Mucho en la lista es en gran medida "le faltaron las cosas que vinieron en la próxima versión"; sin embargo, siempre sobrevivimos hasta que se agregaron ... Algunos de ellos son errores genuinos, sin embargo, lo concederé. –

+0

Acerca de "cosas en la próxima versión" - algunas de estas fueron simplemente tontas. ¿No se permite un setter privado? Ick. Eso debería haber sido una bondad obvia. Los métodos parciales habrían sido un poco más difíciles de detectar la necesidad. Los genéricos eran obviamente necesarios, pero difíciles de definir (es decir, se necesitaba más tiempo). –

28

cadenas Comprobando NULL o vacío se realiza mejor usando:

if (string.IsNullOrEmpty(testString)) 
{ 
} 
+0

Dado que esta pregunta aún recibe bastante tráfico, vale la pena señalar que ahora también tenemos 'String.IsNullOrWhiteSpace'. – Yuck

0

La forma que tengo de poner en práctica las propiedades de una interfaz en C# 3.0 incluso aunque son exactamente lo mismo que la interfaz cuando no estoy cambiando el comportamiento predeterminado de las propiedades automáticas.

p. Ej.

public interface MyInterface 
{ 
    int MyProperty { get; set;} 
} 

public class MyClass : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

public class MyClass2 : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

public class MyClass3 : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

EDITAR: Para abordar algunos de los comentarios sobre esto. No estoy cambiando ningún comportamiento predeterminado de mi getter. Entiendo la diferencia entre clase e interfaz, mi punto es que al marcarlo con la interfaz no debería tener esta propiedad dentro de cada clase de implementación a menos que quiera cambiar el comportamiento predeterminado del getter o setter. ¿Las clases Imagine 500 implementan esta interfaz?

también la falta de Mixins ..

+1

¿Cómo esto no tiene sentido? Aunque es el mismo texto, el significado es muy diferente. Interface solo dice "La propiedad tendrá un getter". La clase dice "compilador, crea un campo privado y devuélvelo sin modificaciones dentro del getter". –

+1

Esta decisión tiene sentido para mí. Sin esto, ¿cómo diferenciaría si su interfaz SOLO requiriera una propiedad obtener, o solo un conjunto de propiedades? ¿Qué pasa si su clase no usó propiedades automáticas (o se extendió con lógica en v2)? –

+0

Sí, pero lo que digo es que una vez que haya implementado la interfaz, esa propiedad debería implementarse detrás de las escenas a menos que quiera cambiarla. Acabo de encontrar, particularmente con objetos de transferencia de datos, que estoy escribiendo el mismo código una y otra vez. –

5

a cabo y ref parámetros

+1

¿Cómo lo manejarías? –

+4

Devuelve un objeto compuesto. –

+0

+1 Sí, esto, 100%. Odio ** que 'TryParse' use parámetros de salida. Sería encantador para 'Int32.TryParse' devolver un objeto' ParseResult 'con las propiedades' Exception' y 'Value'. – Yuck

1

Ampliando la respuesta de Mitch.

Esto es realmente una decisión CLR, no una C#. C# no tiene control sobre los detalles de implementación de la clase System.String de BCL.

True C# podría tener una cadena de caracteres especiales en el compilador y dijo que haremos comprobaciones nulas especiales, pero que en mi humilde opinión sería una mala decisión. String.IsNullOrEmpty es un compromiso aceptable.

+0

gracias por la explicación. – Steve

6

Probablemente el mayor agujero evidente en C# es, para mí, las enumeraciones.

Las enumeraciones de Java son clases seguras de tipo que puede proporcionarle comportamiento, puede implementar interfaces, etc.

C# /. Las enumeraciones de red son simplemente glorificados con todos los problemas que han tenido las constantes int que se remontan a C y C++.

+1

Por otro lado, puede emular fácilmente las enumeraciones de Java complejas escribiéndolas como una clase: p Lo único que se perdería es la capacidad de 'cambiar' en ellos. – JulianR

+0

No hay más que eso, como controlar cuántas instancias hay de un valor nocional a través de la serialización/deserialización, etc. – cletus

1

Aplicación de la rotura en un estuche no vacío.

Verbosidad de enumeraciones, especialmente en sentencias case. Si tengo switch (expr) y expr es una enumeración, no debería ser forzado a calificar completamente cada enumeración en cada caso, a menos que haya un conflicto de nomenclatura.

0

No permitir cambios co/contra-varianza o los derechos de acceso al redefinir la clase base o la aplicación de métodos de interfaz:

public class A 
{ 
    protected virtual Stream method() 
    { 
     //...stuff... 
    } 
} 

public class B : A 
{ 
    // compiler borks... 
    public override FileStream method() 
    { 
     //...more stuff... 
    } 
} 
1

Las excepciones comprobadas habría sido genial. Sé que mucha gente los odia de Java, pero creo que siempre se aplican controles de cordura, especialmente en I/O. Me gusta la mayoría de las cosas que C# cambió y/o agregó en comparación con Java, pero realmente me hubiera gustado que adoptaran excepciones comprobadas. Es demasiado tarde ahora (el marco .NET se ha modificado para que rompan prácticamente todos los programas), pero creo que hubiera sido mejor tenerlos.

0

Odio tener que escribir IEnumerable<MyType> por todo el lugar. Es tan difícil de leer. Preferiría algún tipo de mano corta para que mi código sea más limpio.

Esto SO post lo resume muy bien.

0

Me resulta enormemente irritante que muchos métodos básicos sean estáticos, especialmente en torno a elementos de uso común como cadenas y matrices.

qué:

Array.Sort(myArray); 
String.IsNullOrEmpty(myString); 

en lugar de:

myArray.Sort(); 
myString.IsNullOrEmpty 

no decir que no hay buenas razones para ello y no es un gran problema, pero si JS puede manejarlo, ¿por qué' t C#? *

También el interruptor implementación. Realmente creo que deberían habernos confiado en Fallthrough.

* Llegado a ese punto, echo de menos la sintaxis de cierre de JS también.

0

No me gusta IDisposable/Dispose etc. Viniendo de C++ es muy molesto tener que pensar en la gestión de la memoria en C#. La instrucción using está bien si el objeto desechable solo se usa en una función. Si tiene que pasarse, debe consultar manualmente el recuento o hacer otra cosa para saber cuándo puede deshacerse del objeto.

0

Me gustaría ver objetos de clase como objetos de primera clase en el lenguaje.

Esto le permitiría sobrescribir los métodos estáticos y declararlos en las interfaces.

Cuestiones relacionadas