Reputation: 17605
Suppose we have a struct which permits an implicit cast to some type, say 'string', as follows.
public struct Foo
{
public string Value;
public static implicit operator string(Foo i)
{
return i.Value;
}
}
Let iFoo
be an instance of Foo
. Based on this definition, an assignment with subsequent method call like
string Test = iFoo;
Test = Test.Trim();
is syntactically correct, while a contracted call like
string Test = iFoo.Trim();
is not. What is the exact reason for this? Can the desired behaviour (possibility to call methods of string
on instances of Foo
) be achieved - of course by means of implicit conversion alone? If not, what is the reason for the second piece of code being syntactically incorrect?
Upvotes: 0
Views: 94
Reputation: 113292
An implicit cast allows for two things:
Okay, that sounds a bit tautologous, but let's take those one at a time, the cast first.
Because of the cast you can do:
string Test = ((string)iFoo).Trim();
This works because the expression ((string)iFoo)
has a defined way of working (because of the cast) and when you break down the expression ((string)iFoo).Trim()
to the expressions it is made up from, all of them are syntactic and meaningful and have defined behaviour.
Now, the implicit part of this, is that as syntactic sugar we can leave out the (string)
part that does this casting in certain cases. This is typically done because the "widening" conversion involved is so obvious that the cast would (or at least arguably could) distract the programmer more than it makes things clear to them. Hence for example the in-built implicit cast from int
to long
; with long x = 3
it's absolutely clear what would happen (the long
value x
is now 3L
).
Likewise with DateTime.Now.AddTicks(2)
it's pretty clear that we want the same behaviour to happen as if we called DateTime.Now.AddTicks(2L)
. Forcing us to add an explicit cast obscures more than it makes clear.
It gets a bit less clear with 3L.CompareTo(2)
, since both long
and int
have CompareTo
methods, but there isn't really any way of banning it: implicit casts work from int
to long
, so that's what will happen here.
With 2.CompareTo(3L)
an implicit cast is beginning to be something that would be costing more confusion that it would solve. Even looking at that example myself as the person who wrote it, I'm not sure if it means ((long)2).CompareTo(3L)
or 2.CompareTo((int)3L)
.
When we consider the impact of multiple implicit casts and to multiple types with multiple overloads, the impact in allowing an implicit cast on the left hand side of the .
operator could quickly lead us into situations where it is extremely ambiguous as to just what implicit casts are meant to be called where.
The syntactic sugar of implicit casting will have become syntactic vinegar.
So, it makes sense that there is no implicit casting done with the .
operator.
The code in your answer does not have a syntax error because string Test = iFoo.Trim();
can be interpreted meaningfully by the rules of the language, but a compiler error because by the rules of the language it can only mean "call the 'Trim()' method defined on type 'Foo' or else the 'Trim(T)' extension method where 'T' is either 'Foo' or a base type of 'Foo'". There's no such method, so the syntax is correct, but the result is impossible to fulfil.
Upvotes: 1
Reputation: 391436
No, method calls will be done using different rules and does not involve casting like that. You won't be able to do what you want without:
Upvotes: 3