Question

Is there anything wrong with using an implicit operator like the following:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

I was thinking I could treat as instance of the object as a value type this way, but seeing as I've never seen an example of this I thought maybe there was a reason not to do something like this that someone could point out?

In my actual code I was thinking of doing this as part of a data abstraction layer, so that I could return objects with information describing the underlying data, but allow the logic code to treat it as a value type when all it needs to know about is the value, and at the same time keep it all nice and type safe with the generics.

Was it helpful?

Solution

If all of the following are true:

  • all possible values of your MyClass<T> type (including null if it’s not a value type!) map to a valid value of T

  • the implicit operator never throws (not even for null!)

  • the implicit conversion makes semantic sense and is not confusing to the client programmer

then there is nothing wrong with this. Of course you could do any of these three things, but it would be bad design. In particular, an implicit operator that throws can be very hard to debug because the place where it is called doesn’t say that it is being called.

For example, consider that T? has no implicit conversion to T (where T is, of course, a value type). If there was such an implicit operator, it would have to throw when the T? is null, as there is no obvious value to convert null to that would make sense for any value type T.


Let me give an example where I had trouble debugging an issue where the implicit operator threw:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

Here, GetSomething returned something of a type I wrote which has a user-defined implicit conversion to string. I made absolutely sure that GetSomething could never return null, and yet I got a NullReferenceException! Why? Because the above code is not equivalent to

return some_condition ? (string)GetSomething() : (string)null;

but to

return (string)(some_condition ? GetSomething() : (Something)null);

Now you can see where the null came from!

OTHER TIPS

That's a great pattern. Just keep in mind that in order to use it as a variable of type T, you have to either explicitly cast it to T, or assign it to a variable of type T. The cast will take place automatically in method calls and other things (such as your addition example) that take a T.

Implicit conversion without assignment?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top