2009-10-08 18 views
6

De MSDN:¿Alguna vez hay una excusa para lanzar una excepción de una conversión implícita?

Mediante la eliminación de moldes innecesarias, las conversiones implícitas pueden mejorar la legibilidad del código fuente. Sin embargo, dado que las conversiones implícitas pueden ocurrir sin que el programador las especifique, se debe tener cuidado para evitar sorpresas desagradables. En general, los operadores de conversión implícitos nunca deben arrojar excepciones y nunca perder información para que puedan ser utilizados de manera segura sin la conciencia del programador. Si un operador de conversión no puede cumplir esos criterios, debe marcarse explícitamente.

Si bien no estoy en desacuerdo con cualquier punto particular, y estoy de acuerdo que todo esto es muy bueno, es que alguna vez una razón que es lo suficientemente grande como para justificar romper la parte de las conversiones implícitas no lanzar excepciones?

El caso particular tengo ante mí es uno donde:

  1. Tengo una función que devuelve un objeto de colección personalizada (lo llamaremos FooCollection).
  2. Esta función puede devolver colecciones con un solo elemento, y se puede determinar desde el código fuente si esto sucederá o no. (Con esto me refiero solo a la llamada de función, no a la función en sí)
  3. Si esto sucede, es 99.9% probable que el usuario quiera ese elemento individual, en lugar de una colección con un solo artículo.

ahora, estoy tirando hacia arriba si se debe incluir una conversión implícita de FooCollection =>Foo para ocultar este pequeño detalle de implementación, pero esta conversión sólo funcionará si hay un solo elemento de la colección.

¿Está bien arrojar un Exception en este caso? ¿O debería usar un yeso explícito en su lugar? ¿Alguna otra idea sobre cómo podría lidiar con esto (no, debido a los detalles de implementación, no puedo usar solo dos funciones)?

EDIT: me siento digno de notar que FooCollection no implementa las interfaces o en realidad se extienden Collection como su nombre podría dar a entender, por lo tanto, las respuestas basadas LINQ son inútiles. Además, si bien la colección implementa un índice numérico, no es la forma más intuitiva de tratar con la colección, ya que depende principalmente del índice nombrado.

Respuesta

10

Estoy con las pautas: Nunca deberías arrojar desde una conversión implícita.

Definitivamente no proporcionaría una conversión implícita en este caso. Incluso la idea de un elenco explícito me parece mal: Foo x = (Foo)fooCollection simplemente no parece correcto.

¿Por qué no dejas que el código de llamada se preocupe por la conversión de FooCollection a Foo? El código sería mucho más intuitivo para todo el mundo:

Foo a = fooCollection[0]; 
Foo b = fooCollection.First(); 
Foo c = fooCollection.FirstOrDefault(); 
// etc 
+0

'Foo x = (Foo) fooCollection' tampoco sería" correcto "(aunque se compilaría). 'Foo x = (Foo) fooCollection.x()' sería la forma en que se usaría. –

+0

x() es una función que devuelve un subconjunto de 1 elemento de fooCollection. –

+0

También vea mi edición en la pregunta. –

0

El modelo debe ser explícito. Sería muy extraño poder asignar un FooCollection a un Foo sin al menos un molde.

Dicho esto, los moldes de IMHO no son una buena forma de hacerlo. Incluso si dices que no, usaré una función porque incluso si no tienes control sobre la implementación de estas clases, al menos puedes agregar métodos de extensiones como Foo ToFoo(this FooCollection collection) para realizar el trabajo.

+0

En realidad, estoy seguro del 50% de que tampoco funcionará, ya que esto está en el contexto de C# 4.0 y los tipos dinámicos –

+0

, es decir. No estoy seguro de si el enrutamiento dinámico tiene en cuenta los métodos de extensión o no. ¡Maldita sea, ahora tengo algo más que quiero probar! –

0

Un copnversion implícita de que sólo funciona si hay sólo 1 elemento de la colección? Entonces, de hecho, ¿no funciona la mayor parte del tiempo?

Nunca haría esta conversión implícita. Quédate con explícito. Si el programador que usa su función quiere tener un solo elemento, simplemente debe decirlo a su clase.

1

Está claro que no está bien. ¡Nunca use excepciones para implementar la lógica!

Puede usar el enunciado Linq FooCollection.FirstOrDefault(), que dará nulo o el primer artículo.

Cuestiones relacionadas