views:

1067

answers:

3

Right now I'm having it with Guids.

I certainly remember thah throughout the code in some places this implicit conversion works, in other does not. Until now I fail to see the pattern.

How the compiler decides that it cannot? I mean, the type method Guid.ToString() is present, isn't it called whenever this transformation is needed?

Can someone please tell me under what circumstances this transformation is done automatically and when I have to call .ToString() explicitly?

+8  A: 

In short, when there is an implicit or explicit conversion operator defined:

class WithImplicit {
    public static implicit operator string(WithImplicit x) {
        return x.ToString();}
}
class WithExplicit {
    public static explicit operator string(WithExplicit x) {
        return x.ToString(); }
}
class WithNone { }

class Program {
    static void Main() {
        var imp = new WithImplicit();
        var exp = new WithExplicit();
        var none = new WithNone();
        string s1 = imp;
        string s2 = (string)exp;
        string s3 = none.ToString();
    } 
}
Marc Gravell
Just looked it up for myself. Cannot believe I missed this thing in all these years with C#. I suppose never needed it really... Thanks for making me learn something new today.
User
And where do I have to define this operator? In the Type class I guess? I cannot add static extensions to these WithImplicit and WithExplicit classes.
User
No; there is no such thing as an extension operator.
Marc Gravell
+2  A: 

The only place where you effectively don't need to call ToString() yourself is when concatenating strings.

Guid g;
int i;
string s = "Hello "+g+' '+i;

Then there are some situations where the call is made by the .NET Framework, such as in String.Format().

Other than that, the compiler will only convert a type if it is known to be compatible (e.g. base class or implementing an interface or via an explicitly coded conversion operator). When you use a cast and the compiler knows that the types cannot be compatible (e.g. not in the same inheritance line, and not interfaces), it will also say that it cannot convert it. The same goes for generic type parameters.

Lucero
Not correct; the compiler also respects conversion operators. See my post for examples of both implicit and explicit conversions, which do *not* require the caller to use either ToString() or string concatenation.
Marc Gravell
You're right about conversion operators, but I usually avoid them so I didn't mention them here. I'll change my response.
Lucero
+1  A: 

No, there is no implicit conversion from GUID to String, so that doesn't work anywhere at all in the code.

It only works where there is an explicit conversion, but the conversion might not be very visible. For example when you concatenate strings:

string id = "--" + guidValue + " : " + num;

This may look like an implicit conversion from GUID to String, but it isn't. The code that is generated actually looks like this:

string id = String.Concat(new object[] { "--", guidValue, " : ", num });

All operands are cast to the type Object and placed in an array. The String.Concat method then calls the ToString method for each item in the array to get the string representation for them.

Guffa