2010-09-27 6 views
14

Duplicar posibles:
Most common or vicious mistakes in C# development for experienced C++ programmerscomportamientos programador malo C++ en C#

Soy un largo tiempo de programador C++ a punto de empezar a trabajar en proyectos de C#.

¿Cuáles son algunos cambios conceptuales a tener en cuenta, y lo más importante, qué debo evitar hacer en C# que normalmente haría en C++? ¿Qué malos hábitos traen los programadores de C++ a C# que deberían perder?

Tengo una lista de libros de C# que tengo la intención de leer. Me gustaría aumentar eso con las experiencias de otros programadores que han hecho esta misma transición porque probablemente tenderé a cometer los mismos errores que ellos; Me gustaría evitar eso antes de que suceda.

+17

¿Qué hay del cambio conceptual de que son idiomas diferentes? El mal hábito es intentar adivinar-programa C# porque conoces C++. C++ no es C#. ** Obtenga un libro de C# para principiantes para que pueda aprender C# principiante. Eso es todo. Si pudiera programar C# porque puede programar C++, no serían idiomas diferentes. – GManNickG

+1

@Gman +1 Sí, hay una suposición en esta pregunta de que la capacidad de programación en uno se transferirá a la otra. Soy principalmente un programador de vb.net (continúa, ríete bien: D) y si hubiera pasado directamente de vb6 a .net sin haber aprendido los conceptos básicos/cambios fundamentales, habría escrito algunos * awful * .net ¡código! –

+0

@GMan: tengo la intención de tratarlo como un idioma separado. Mi preocupación es sobre los matices en las características del lenguaje que pueden hacerme tropezar. Por ejemplo, la distinción entre estructuras y clases en C# que Tergiver señaló. Espero ganar de las experiencias de los demás. – JoshD

Respuesta

8

Sólo un ejemplo:

En C++ no hay diferencia entre una estructura y una clase. Con el paso de los años, esto ha llevado a grupos e individuos a definir sus propias reglas para usar una sobre otra.

En C# hay una diferencia concreta. Una estructura es un tipo de valor y una clase es un tipo de referencia.

Cuando los programadores C++ traen a C# sus viejas y arbitrarias definiciones de clase/estructura, tienden a suceder cosas inesperadas.

Aquí está una bastante buena lectura para los programadores de C++ que se mueven a C#: http://msdn.microsoft.com/en-us/magazine/cc301520.aspx

+1

Ellos se comportan de manera diferente, pero el compilador generalmente te grita cuando los has usado incorrectamente, ¿no? Por lo general, no es un error de tiempo de ejecución? Al menos en mi experiencia ... – mpen

+2

El mero hecho de que una clase sea tipo de referencia y una estructura sea un tipo de valor causará problemas no deseados, como cuando se pasa a un método y se espera que se modifique el objeto original. También puede inflar fácilmente el uso de la memoria debido a todas las copias involuntarias. Estos problemas no se detectarán durante la compilación o el tiempo de ejecución, y deben depurarse manualmente. – KallDrexx

3

peor que he visto es

1) usando excesivamente contexto crítico (bloqueo usando monitor o bloquear() declaración) en un proyecto web! El resultado es, con bastante frecuencia, la reducción de IIS a un sistema de subproceso único más o menos.

2) Demasiado procesamiento de cadenas. Solía ​​hacer todo por sí mismo para no depender del framework. Las cadenas son inmutables en C# mientras no están en C++.

3) Utilizando inseguro código porque pueden y no porque deberían.

4) No confiar en GC

+0

-1 porque 1, 2, 3 son verdaderos también para el buen estilo de C++. 4) está mal. Realmente no siempre puedes confiar en eso. Los recursos del sistema de miembros son un ejemplo. – ybungalobill

+0

"4) es incorrecto. Realmente no siempre puedes confiar en él". ¿No dije? :) – Aliostad

+0

@Aliostad: * por favor * lea mi respuesta y entrégueme la solución tan elegante que ofrece C++. – ybungalobill

3

Los más grandes:

  • C# no tiene herencia múltiple, que utiliza interfaces de lugar.
  • No puede controlar la vida útil de un objeto o utilizar eso para su ventaja.
  • El operador de igualdad de C# no siempre hace lo que crees que debería. A veces se compara el contenido de una variable y, a veces, la dirección de la variable.
+1

Puede y debe controlar absolutamente la vida útil de los objetos en un entorno de GC. ¡Cuidado con tus referencias! – Tergiver

+2

Eliminar todas las referencias no significa el final de la vida de un objeto, a menos que fuerce GC. Es por eso que también tiene IDisposable y el uso para limpiar otros recursos más rápido. El control de la vida útil es mucho más flexible. –

+1

@Greg: no hay nada de malo en tu lógica. A lo que me opongo es a la actitud de complacencia. Desde el punto de vista de su aplicación, un objeto está muerto y desaparecido cuando ya no contiene una referencia. Un recolector de basura es una simulación de un sistema con memoria infinita. El problema es que es solo una simulación y sabemos que no hay memoria infinita. Eso significa que todavía somos responsables de la duración del objeto. – Tergiver

2

No mucho, pasar de C++ a C# es un tipo de degradación, por lo que no puede hacer "cosas malas". La única cosa que puedo pensar es confiando en la gestión de memoria automática:

class A { 
    ofstream file; 
public: 
    // bla bla 
}; 

En C# es necesario implementar toda la basura IDisposable para que no escape el archivo ... Usted puede olvidar fácilmente.

Los comportamientos del programador de Bad C# en C++ serían un tema más interesante.

+0

Si lo implementa correctamente (IDisposable + Finalizer), incluso si lo olvida, GC se activará, aunque no será inmediato.¡Si se supone que debes olvidar, en C++ hay tantas cosas que olvidarás! Todos esos recuerdos que tienes que liberar manualmente ... – Aliostad

+3

@Aliostad: implementar IDisposable no será mucho. Si pierde, un GC cerrará el archivo de todos modos, incluso sin IDisposable. Pero puede que nunca suceda. A diferencia de C#, no libero memoria (u otros recursos) manualmente en C++. ¿Has oído hablar de RAII? Resuelve casi todos los problemas, al menos mucho más que GC. – ybungalobill

+3

RAII al rescate :) –

1

Cosas que cambian al pasar de C++ a C#:

  • Usar las propiedades cuando sea posible para representar datos de los miembros de clase
  • utilizan interfaces en situaciones que podrían requerir la herencia múltiple en C++
  • Use eventos para notificación en lugar de transferir funciones de devolución de llamada (delegados) a las clases
  • Recuerde utilizar la construcción using() {} para asegurarse de que recursos como archivos y conexiones de base de datos se eliminen cuando se salgan del alcance.

Eso es justo al lado de la parte superior de mi cabeza

1

El cambio más grande para mí fue dejar de preocuparse por la liberación de memoria, hilo de seguridad (quiero decir que todavía tiene que bloquear las cosas, pero C# ha sido diseñado para el roscado de día 1 por lo que no hay inconvenientes desagradables) y archivos de encabezado.

Si se siente tentado de usar/inseguro, es casi seguro que está equivocado.

aprenden la biblioteca de clases.

8

Una cosa a tener en cuenta es que C# no tiene destructores en el mismo sentido que lo hace C++. Un método con la firma de un destructor de C++ se denomina finalizador en C# y no es necesario (y en algunos casos no se recomienda) implementarlo.

Consulte la interfaz IDisposable y estos artículos sobre la recolección de basura: Everybody thinks about garbage collection the wrong way y Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework.

+1

Me pregunto qué tan difícil hubiera sido para Microsoft haber agregado algo análogo a una etiqueta de "Uso" a la declaración de un campo iDisposable, para indicar que el campo debería estar ".disposed" cuando el objeto en sí. De lo contrario, es difícil garantizar la eliminación de objetos iDisposable que se crean a través de inicializaciones (en lugar de en el constructor). – supercat

+2

En realidad se llama ** destructor ** en el mundo C#. Para peor. –

+0

+1 para una lectura muy interesante! – SingleNegationElimination

2

Hay cosas que puede hacer en C++ que no puede hacer en C#, y viceversa. No es probable que te causen problemas.

Mayor cambio: deshacerse de la mentalidad de "instanciación es la inicialización". La recolección de basura significa que no necesita preocuparse de asignar o liberar memoria (excepto cuando lo hace), sino que también significa que no puede confiar en que algo se salga del alcance y haga que el destructor lo limpie después de usted.

Aprenda la construcción "using", en C#, y asegúrese de usarla.

Segundo cambio - en C++ "clase" y "estructura" son efectivamente sinónimos. En C#, son cosas muy diferentes.

+1

Un bloque "usar" proporciona algo análogo al comportamiento de C++ de disponer recursos cuando el bloque sale. Desafortunadamente, no hay forma de etiquetar los campos para la eliminación automática cuando se elimina un objeto en sí mismo, ni existe una forma agradable de limpiar un objeto cuya inicialización falla. – supercat

2

No es un hábito "malo", pero algo que definitivamente debe tener en cuenta al cambiar de C++ a C#: confiando en los destructores para hacer su limpieza. En su lugar, es necesario recordar para implementar IDisposable y controlar la vida de su objeto de una declaración using.

7
  • no hay RAII implícita, usted tiene que codificar explícitamente
  • no hay protección const
  • propiedades son pares de métodos, no es un valor
  • cuando la iteración se inicia antes de la recolección y terminan a las al final de la misma (en términos de C++)
  • foreach es como usar const_iterator lista
  • como su nombre lo dice, no es una lista, es una una matriz
  • los genéricos se resuelven en el momento de la compilación, no al momento de usarlos
Cuestiones relacionadas