It's worth being clear on terminology here. sc
isn't an object, it's a variable. The value of the variable is a reference. The reference may be null, or it may be a reference to a real object.
Now, as for why it's not as simple as it sounds...
In this code:
sc.SomeMethod();
... there are two operations:
- Load value of
sc
onto the execution stack
- Execute
SomeMethod
via the reference on the execution stack
It's the second operation which fails, and that operation doesn't "know" about the first operation, really.
It becomes worse when there are more operations involved. What about:
Foo().Bar().SomeMethod()
What would you expect the exception to show in this case?
Personally I rarely find it that hard to work out where the exception is coming from - the line number normally makes it fairly clear, and the situations in which it's not clear are usually precisely the situations where there's a long expression which couldn't easily give a single answer in the exception anyway.
I guess it would be possible for the CLR/compiler to agree on an extra table, like the line number mapping, which says "for IL instruction X, the top of the execution stack was from an expression with diagnostic message Y". It feels like it would be pretty cumbersome though - and as I say, it shouldn't really give you that much of a headache.