8

From MSDN:

By eliminating unnecessary casts, implicit conversions can improve source code readability. However, because implicit conversions can occur without the programmer's specifying them, care must be taken to prevent unpleasant surprises. In general, implicit conversion operators should never throw exceptions and never lose information so that they can be used safely without the programmer's awareness. If a conversion operator cannot meet those criteria, it should be marked explicit.

While I don't disagree with any particular point, and I agree that this is all very good, is there ever a reason that is great enough to warrant breaking the part about implicit conversions not throwing exceptions?

The particular case I have before me is one where:

  1. I have a function, which returns a custom collection object (we'll call it FooCollection).
  2. This function can return collections with a single item, and it can be determined from the source code whether this will happen or not. (by this I mean just the function call, not the function itself)
  3. If it does happen, it is 99.9% likely that the user wants that single item, rather than a collection with a single item.

Now, I'm tossing up whether to include an implicit conversion from FooCollection => Foo to hide this little implementation detail, but this conversion will only work if there is a single item in the collection.

Is it ok to throw an Exception in this case? Or should I be using an explicit cast instead? Any other ideas about how I could deal with this (no, due to implementation details I can't just use two functions)?

EDIT: I feel it worthy of noting that FooCollection doesn't implement any interfaces or actually extend Collection as the name might imply, hence the LINQ based answers are useless. Also, while the collection does implement a numeric index, it isn't the most intuitive way of dealing with the collection as it relies on named index mostly.

Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222

4 Answers4

11

I'm with the guidelines: You shouldn't ever throw from an implicit conversion.

I definitely wouldn't provide an implicit conversion in this case. Even the idea of an explicit cast feels wrong to me: Foo x = (Foo)fooCollection just doesn't seem right.

Why don't you just let the calling code worry about the conversion from FooCollection to Foo? The code would be much more intuitive for everyone:

Foo a = fooCollection[0];
Foo b = fooCollection.First();
Foo c = fooCollection.FirstOrDefault();
// etc
LukeH
  • 263,068
  • 57
  • 365
  • 409
  • `Foo x = (Foo)fooCollection` wouldn't be 'right' either (though it'd compile). `Foo x = (Foo)fooCollection.x()` would be the way it would be being used. – Matthew Scharley Oct 08 '09 at 12:09
  • x() being a function that returns a subset of 1 item from fooCollection. – Matthew Scharley Oct 08 '09 at 12:10
  • Either way, you're still trying to cast some collection of `Foo` to `Foo` itself, which feels weird to me. Why not just let the calling code do `Foo x = fooCollection.x()[0]` or something similar? – LukeH Oct 08 '09 at 12:20
  • Among other things, it feels messy. But throwing an exception from an implicit conversion doesn't feel right either. Oh well, I suppose SO has spoken either way anyway :) – Matthew Scharley Oct 08 '09 at 12:22
  • I'd word is slightly differently: any object instance which ever throws when performing an implicit conversion should be considered broken. If e.g. a non-threadsafe object instance becomes corrupt as a result of simultaneous actions by multiple threads, it may be appropriate for that instance to throw an exception in what would normally be a widening typecast, but only *because the instance is broken*. – supercat Sep 26 '12 at 19:22
  • Just something to consider: Microsoft does throw exceptions during implicit conversions. For instance: ```System.Index index = 1;``` works whereas ```System.Index index = -1;``` throws an exception. – Praveen Angyan Mar 01 '23 at 19:40
1

It clearly is not OK. Never ever use exceptions to implement logic!

You may use the Linq-Statement FooCollection.FirstOrDefault(), which will give null or the first item.

Thomas Weller
  • 11,631
  • 3
  • 26
  • 34
0

The cast should be explicit. It'll be very strange to be able to assign a FooCollection to a Foo without at least a cast.

That being said, IMHO casts are not a good way to do this. Even if you say no to it I'll use a function because even if you don't have control over the implementation of these classes, you can at least add Extensions Methods like Foo ToFoo(this FooCollection collection) to get the job done.

Julien Lebosquain
  • 40,639
  • 8
  • 105
  • 117
0

An implicit copnversion that does only work if there is just 1 item in the collection? So, in fact, it doesn't work most of the time?

I would never make this conversion implicit. Stick with explicit. If the programmer using your function wants to have the single item, he should just tell your class.

Maximilian Mayerl
  • 11,253
  • 2
  • 33
  • 40