This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Compile-time and runtime casting c#
As I understand it, the following code will always compile, and will additionally always fail at run-time by throwing an InvalidCastException.
Example:
public class Post { }
public class Question : Post { }
public class Answer : Post
{
public void Fail()
{
Post p = new Post();
Question q = (Question)p; // This will throw an InvalidCastException
}
}
My questions are...
If my assumptions are off, then can someone provide an example demonstrating how they're off?
If my assumptions are correct, then why doesn't the compiler warn against this error?
There are a couple of reasons why this conversion is allowed.
First, as people have said in other answers, the cast operator means "I know more than you do; I guarantee you that this conversion will succeed and if I am wrong, throw an exception and crash the process". If you are lying to the compiler, bad things are going to happen; you in fact are not making that guarantee, and the program is crashing as a result.
Now, if the compiler can tell that you are lying to it, then it can catch you in the lie. The compiler is not required to be arbitrarily clever in catching you in your lies to it! The flow analysis needed to determine that an expression of type Base is never going to be of type Derived is complex; considerably more complex than the logic we already implement to catch things like unassigned local variables. We have better ways to spend our time and effort than in improving the compiler's ability to catch you out in obvious lies.
The compiler therefore typically reasons only about types of expressions, not about possible values. Solely from the type analysis it is impossible to know whether or not the conversion will succeed. It might succeed, and so it is allowed. The only casts that are disallowed are the ones that the compiler knows will always fail from the type analysis.
Second, it is possible to say (Derived)(new Base()) where Derived is a type that implements type Base and have it not fail at runtime. It is also possible for (Base)(new Base()) to fail with an invalid cast exception at runtime! True facts! These are extraordinarily rare situations but they are possible.
For more details, see my articles on the subject:
Chained user-defined explicit conversions in C#
Chained user-defined explicit conversions in C#, Part Two
Chained user-defined explicit conversions in C#, Part Three
A Post could, under some cases, be cast to a Question. By performing the cast, you're telling the compiler, "This will work, I promise. If it doesn't you're allowed to throw an invalid cast exception."
For example, this code would work fine:
Post p = new Question();
Question q = (Question)p;
A cast is expressly stating that you know better than the compiler what this actually is. You may want to do something like the as or is keywords?
The point is that p could be a Question, as question inherits from Post.
Consider the following:
public class Post { }
public class Question : Post { }
public class Banana { }
static class Program {
public static void Main(params string[] args) {
Post p = new Question();
Question q = (Question)p; // p IS a Question in this case
Banana b = (Banana)p; // this does not compile
}
}
When you do an explicit cast, you are telling the compiler "I know something you don't".
You are in essence overriding the normal logic of the compiler - p might be a Question (so, the compiler will compile), you are telling the compiler that you know it is (even though it isn't, hence runtime exception).
1) Your assumption is off. Somebody could always implement an explicit conversion operator for Question to convert from Post:
public class Question`
{
// some class implementation
public static explicit operator Question(Post p)
{
return new Question { Text = p.PostText };
}
}
2) An Explicit cast is your way of telling the compiler that you know better than it does. If you want something to use when you're not sure if a cast will succeed or not and don't want a runtime exception, use the is and as operators.
The compiler treats p as a variable, so, it doesn't try to track it's value. If it did, it'd take so long for analyzing the entire application. Some static analysis tools do like FxCop.
The Compiler sees a Post, but it didn't track the assignment, and it knows that maybe:
Post p = new Question();
So, it passes it normally.
You know you cannot do:
Question q = p;
The difference is in this one you are trying to tell the compiler to use what it knows to validate this, and it knows the Post is not necessarily a Question.
In the original version you are telling the compiler "I know it is, and I will set this explicitly, get off my way and I'll take the exception if what I know is wrong", so, it listens to you and gets off your way!
You assumptions are correct: It will compile and it will fail at runtime.
In your small example it is obvious that the cast will fail, but the compiler have no way of knowing this. Since Post is a supertype of Question you could assign a Question to p, and since you make the cast you do declare a willingness take some responsibility from the compiler. Had you been trying to assign a string or something else not part of the same inheritance branch the compiler should warn you. Conversely you can always try to cast object to any type.
But having the compiler complaining about your specific example would mean that no casts would be allowed.
Wow Jeremy, I ran into this exact problem recently! So I made this handy extension method that maps two models that share a few identical properties. The intention was to use it when class A inherits from class B to map class B to class A. Hope you find it helpful!
public static class ObjectHelper
{
public static T Cast<T>(this Object source)
{
var destination = (T)Activator.CreateInstance(typeof(T));
var sourcetype = source.GetType();
var destinationtype = destination.GetType();
var sourceProperties = sourcetype.GetProperties();
var destionationProperties = destinationtype.GetProperties();
var commonproperties = from sp in sourceProperties
join dp in destionationProperties on new { sp.Name, sp.PropertyType } equals
new { dp.Name, dp.PropertyType }
select new { sp, dp };
foreach (var match in commonproperties)
{
match.dp.SetValue(destination, match.sp.GetValue(source, null), null);
}
return destination;
}
}
FYI, it will probably only work if the two objects exists in the same assembly.
Much of the code came from here: Mapping business Objects and Entity Object with reflection c#
Related
I think I understand why this small C# console application will not compile:
using System;
namespace ConsoleApp1
{
class Program
{
static void WriteFullName(Type t)
{
Console.WriteLine(t.FullName);
}
static void Main(string[] args)
{
WriteFullName(System.Text.Encoding);
}
}
}
The compiler raises a CS0119 error: 'Encoding' is a type which is not valid in the given context. I know that I can produce a Type object from its name by using the typeof() operator:
...
static void Main(string[] args)
{
WriteFullName(typeof(System.Text.Encoding));
}
...
And everything works as expected.
But to me, that use of typeof() has always seemed somewhat redundant. If the compiler knows that some token is a reference to a given type (as error CS0119 suggests) and it knows that the destination of some assignment (be it a function parameter, a variable or whatever) expects a reference to a given type, why can't the compiler take it as an implicit typeof() call?
Or maybe the compiler is perfectly capable of taking that step, but it has been chosen not to because of the problems that might generate. Would that result in any ambiguity/legibility issues that I cannot think of right now?
If the compiler knows that some token is a reference to a given type (as error CS0119 suggests) and it knows that the destination of some assignment (be it a function parameter, a variable or whatever) expects a reference to a given type, why can't the compiler take it as an implicit typeof() call?
First off, your proposal is that the compiler reason both "inside to outside" and "outside to inside" at the same time. That is, in order to make your proposed feature work the compiler must both deduce that the expression System.Text.Encoding refers to a type and that the context -- a call to WriteFullName -- requires a type. How do we know that the context requires a type? The resolution of WriteFullName requires overload resolution because there could be a hundred of them, and maybe only one of them takes a Type as an argument in that position.
So now we must design overload resolution to recognize this specific case. Overload resolution is hard enough already. Now consider the implications on type inference as well.
C# is designed so that in the vast majority of cases you do not need to do bidirectional inference because bidirectional inference is expensive and difficult. The place where we do use bidirectional inference is lambdas, and it took me the better part of a year to implement and test it. Getting context-sensitive inference on lambdas was a key feature that was necessary to make LINQ work and so it was worth the extremely high burden of getting bidirectional inference right.
Moreover: why is Type special? It's perfectly legal to say object x = typeof(T); so shouldn't object x = int; be legal in your proposal? Suppose a type C has a user-defined implicit conversion from Type to C; shouldn't C c = string; be legal?
But let's leave that aside for a moment and consider the other merits of your proposal. For example, what do you propose to do about this?
class C {
public static string FullName = "Hello";
}
...
Type c = C;
Console.WriteLine(c.FullName); // "C"
Console.WriteLine(C.FullName); // "Hello"
Does it not strike you as bizarre that c == C but c.FullName != C.FullName ? A basic principle of programming language design is that you can stuff an expression into a variable and the value of the variable behaves like the expression, but that is not at all true here.
Your proposal is basically that every expression that refers to a type has a different behaviour depending on whether it is used or assigned, and that is super confusing.
Now, you might say, well, let's make a special syntax to disambiguate situations where the type is used from situations where the type is mentioned, and there is such a syntax. It is typeof(T)! If we want to treat T.FullName as T being Type we say typeof(T).FullName and if we want to treat T as being a qualifier in a lookup we say T.FullName, and now we have cleanly disambiguated these cases without having to do any bidirectional inference.
Basically, the fundamental problem is that types are not first class in C#. There are things you can do with types that you can only do at compile time. There's no:
Type t = b ? C : D;
List<t> l = new List<t>();
where l is either List<C> or List<D> depending on the value of b. Since types are very special expressions, and specifically are expressions that have no value at runtime they need to have some special syntax that calls out when they are being used as a value.
Finally, there is also an argument to be made about likely correctness. If a developer writes Foo(Bar.Blah) and Bar.Blah is a type, odds are pretty good they've made a mistake and thought that Bar.Blah was an expression that resolves to a value. Odds are not good that they intended to pass a Type to Foo.
Follow up question:
why is it possible with method groups when passed to a delegate argument? Is it because usage and mentioning of a method are easier to distinguish?
Method groups do not have members; you never say:
class C { public void M() {} }
...
var x = C.M.Whatever;
because C.M doesn't have any members at all. So that problem disappears. We never say "well, C.M is convertible to Action and Action has a method Invoke so let's allow C.M.Invoke(). That just doesn't happen. Again, method groups are not first class values. Only after they are converted to delegates do they become first class values.
Basically, method groups are treated as expressions that have a value but no type, and then the convertibility rules determine what method groups are convertible to what delegate types.
Now, if you were going to make the argument that a method group ought to be convertible implicitly to MethodInfo and used in any context where a MethodInfo was expected, then we'd have to consider the merits of that. There has been a proposal for decades to make an infoof operator (pronounced "in-foof" of course!) that would return a MethodInfo when given a method group and a PropertyInfo when given a property and so on, and that proposal has always failed as too much design work for too little benefit. nameof was the cheap-to-implement version that got done.
A question you did not ask but which seems germane:
You said that C.FullName could be ambiguous because it would be unclear if C is a Type or the type C. Are there other similar ambiguities in C#?
Yes! Consider:
enum Color { Red }
class C {
public Color Color { get; private set; }
public void M(Color c) { }
public void N(String s) { }
public void O() {
M(Color.Red);
N(Color.ToString());
}
}
In this scenario, cleverly called the "Color Color Problem", the C# compiler manages to figure out that Color in the call to M means the type, and that in the call to N, it means this.Color. Do a search in the specification on "Color Color" and you'll find the rule, or see blog post Color Color.
Given this highly simplified example:
abstract class Animal { }
class Dog : Animal
{
public void Bark() { }
}
class Cat : Animal
{
public void Mew() { }
}
class SoundRecorder<T> where T : Animal
{
private readonly T _animal;
public SoundRecorder(T animal) { _animal = animal; }
public void RecordSound(string fact)
{
if (this._animal is Dog)
{
((Dog)this._animal).Bark(); // Compiler: Cannot convert type 'T' to 'Dog'.
((Dog)(Animal)this._animal).Bark(); // Compiles OK
}
}
}
Why does the compiler complain about the single type cast (Dog)this._animal? I just can't get why compiler seems to need help by doing two casts. _animal cannot be anything else than an Animal, can it?
Of course this question is motivated by a real life example where I had to modify existing code in a way that a similar cast was the most convenient way to do it, without refactoring the whole lot. (Yes, using composition rather than inheritance ;) ).
EDIT: This is an attempted restatement of Polity's answer - I
think I know what he's trying to say, but I could be wrong.
My original answer (below the line) is still in some ways the
canonical one: the compiler rejects it because the language
specification says it has to :) However, in an attempt to guess
the view of the language designers (I've never been part of the C#
design committee, and I don't think I've asked them about this, so
it really is guesswork...) here goes...
We're used to thinking about the validity of conversions "at
compile time" or "at execution time". Usually implicit conversions
are ones which are compile-time-guaranteed to be valid:
string x = "foo";
object y = x;
That can't go wrong, so it's implicit. If something can go wrong,
the language is designed so that you have to tell the compiler,
"Trust me, I believe it'll work at execution time even though you
can't guarantee it now." Obviously there's a check at execution time
anyway, but you're basically telling the compiler you know what
you're doing:
object x = "foo";
string y = (string) x;
Now the compiler already prevents you from attempting conversions
which it believes can never work1 in a useful way:
string x = "foo";
Guid y = (Guid) x;
The compiler knows there's no conversion from string to Guid, so
the compiler doesn't believe your protestations that you know what
you're doing: you clearly don't2.
So those are the simple cases of "compile time" vs "execution time"
checking. But what about generics? Consider this method:
public Stream ConvertToStream<T>(T value)
{
return (Stream) value;
}
What does the compiler know? Here we have two things which can vary:
the value (which varies at execution time, of course) and the type
parameter T, which is specified at a potentially different
compile time. (I'm ignoring reflection here, where even T is only
known at execution time.) We may compile the calling code later,
like this:
ConvertToStream<string>(value);
At that point, the method doesn't make sense if you replace the type
parameter T with string, you end up with code which wouldn't
have compiled:
// After type substitution
public Stream ConvertToStream(string value)
{
// Invalid
return (Stream) value;
}
(Generics don't really work by doing this sort of type substitution
and recompiling, which would affect overloading etc - but it can
sometimes be a helpful way of thinking about it.)
The compiler can't report that at the time when the call is
compiled - the call doesn't violate any constraints on T, and the
body of the method should be viewed as an implementation detail. So
if the compiler wants to prevent the method from ever being called
in a way which introduces a non-sensical conversion, it has to do
so when the method itself is compiled.
Now the compiler/language isn't always consistent in this approach.
For example, consider this change to the generic method, and the
"following type substitution when called with T=string" version:
// Valid
public Stream ConvertToStream<T>(T value)
{
return value as Stream;
}
// Invalid
public Stream ConvertToStream(string value)
{
return value as Stream;
}
This code does compile in the generic form, even though the
version after type substitution doesn't. So maybe there's a deeper
reason. Maybe in some cases there simply wouldn't be suitable IL to
represent the conversion - and the easier cases aren't worth making
the language more complicated for...
1 It sometimes gets this "wrong", in that there are times
when a conversion is valid in the CLR but not in C#, such as int[]
to uint[]. I'll ignore these edge cases for the moment.
2 Apologies to those who dislike the anthropomorphisation
of the compiler in this answer. Obviously the compiler doesn't
really have any emotional view of the developer, but I believe it
helps get the point across.
The simple answer is that the compiler complains because the language specification says it has to. The rules are given in section 6.2.7 of the C# 4 spec.
The following explicit conversions exist for a given type parameter T:
...
From a type parameter U to T, provided T depends on U. (See section 10.1.5.)
Here Dog doesn't depend on T, so there's no conversion allowed.
I suspect this rule is in place to avoid some obscure corner cases - in this case it's a bit of a pain when you can logically see that it should be a valid attempted conversion, but I suspect that codifying that logic would make the language more complicated.
Note that an alternative might be to use as instead of is-then-cast:
Dog dog = this._animal as Dog;
if (dog != null)
{
dog.Bark();
}
I'd argue that's cleaner anyway, in terms of only performing the conversion once.
The problem is that the compiler can't guarantee that _animal can be casted to Dog since the only restriction you give the type parameter of SoundRecorded is that the type should be Animal OR inherit from Animal. So the compiler is practically thinking: what if you construct a SoundRecorder<Cat>, the cast operation then is invalid.
Unfortunatly (or not), the compiler isn't smart enough to see that you safely protected your code from ever reaching there by doing the 'is' check in advance.
If you were to store the given animal as an actual animal, this wouldn't be a problem since the compiler always allows any cast from a base type to a derived type. The compiler doesnt allow a cast from Dog to Cat though
EDIT See Jon Skeets answer for a more concrete explanation.
This is probably because you are specifying that the generic type extends Animal, so SoundRecorder could be instanciated with Cat as the generic type. Therefore, the compiler cannot permit you to cast an arbitrary subclass of Animal to some other subclass of Animal. If you want to avoid the double cast, try doing the following:
var dog = _animal as Dog;
if(dog != null)
{
dog.Bark();
}
This article touches on the topic of casting generic parameters
There is no explicit type conversion exist between Animal to Dog since your constrains says T must be of type Animal. Though Dog ‘Is a’ an Animal , the compiler doesn't know that T is Dog.
Therefore, it doesn't let you cast.
You can either approach this through implicit conversion
implicit operator Animal(Dog myClass)
or can use something like below
Dog d = _animal as Dog;
As of C# 7.0 you can now use declaration pattern to check the run-time type of an expression and, if a match succeeds, assign an expression result to a declared variable.
public void RecordSound()
{
if (_animal is Dog dog)
{
dog.Bark();
}
}
Just wanted to mention this, even though it does not answer the 'why' part of your question. There are already some great answers here for this part.
Consider the following example program:
using System;
public delegate string MyDelegateType(int integer);
partial class Program
{
static string MyMethod(int integer) { return integer.ToString(); }
static void Main()
{
Func<int, string> func = MyMethod;
// Scenario 1: works
var newDelegate1 = new MyDelegateType(func);
newDelegate1(47);
// Scenario 2: doesn’t work
dynamic dyn = func;
var newDelegate2 = new MyDelegateType(dyn);
newDelegate2(47);
}
}
The first one works as expected — the conversion to MyDelegateType succeeds. The second one, however, throws a RuntimeBinderException with the error message:
Cannot implicitly convert type 'System.Func<int,string>' to 'MyDelegateType'
Is there anything in the C# specification that allows for this behaviour, or is this a bug in Microsoft’s C# compiler?
Good catch Timwi.
Our support for dynamic method groups is weak. For example, consider this simpler case:
class C
{
public void M() {}
}
class P
{
static void Main()
{
dynamic d = new C();
C c = new C();
Action a1 = c.M; // works
Action a2 = d.M; // fails at runtime
The d.M is interpreted as a property get (or field access) by the dynamic runtime, and when it resolves as a method group, it fails at runtime.
The same thing is happening in your case, it is just a bit more obscure. When you say MyDelegate x = new MyDelegate(someOtherDelegate); that is treated by the compiler just as if you'd said MyDelegate x = someOtherDelegate.Invoke;. The dynamic runtime piece does not know to do that transformation, and even if it did, it couldn't handle resolving the method group that is the result of the .Invoke portion of the expression.
Is there anything in the C# specification that allows for this behaviour, or is this a bug in Microsoft’s C# compiler?
The spec does not call out that this should be a runtime error, and does imply that it should be handled correctly at runtime; clearly the implementation does not do so. Though it is a shortcoming of the implementation I wouldn't call this a "bug" because we deliberately made the behaviour you've discovered. We did not have the resources to make these kinds of expressions work exactly right, so we left them as errors. If we ever get a good way to represent method groups in the dynamic runtime, we might implement it.
Similarly there is no way in dynamic code to represent the notion of "this dynamic thing is a lambda expression where the types of the parameters are to be determined at runtime". If we have a good way to represent those in the future, we might do the work.
Sam talked a bit about this back in 2008; see his article on it:
http://blogs.msdn.com/b/samng/archive/2008/11/02/dynamic-in-c-ii-basics.aspx
I've run in to this limitation too. Although I couldn't answer the why better than Eric Lippert, there is a straight forward workaround.
var newDelegate2 = new MyDelegateType(x => dyn(x));
It implicitly gets the static signature from the delegate and the dynamic invocation works without any more info. This works for delegates and, as a bonus, dynamic callable objects.
Given a couple types like this:
interface I {}
class C : I {}
How can I do a static type cast? By this I mean: how can I change its type in a way that gets checked at compile time?
In C++ you can do static_cast<I*>(c). In C# the best I can do is create a temporary variable of the alternate type and try to assign it:
var c = new C();
I i = c; // statically checked
But this prevents fluent programming. I have to create a new variable just to do the type check. So I've settled on something like this:
class C : I
{
public I I { get { return this; } }
}
Now I can statically convert C to I by just calling c.I.
Is there a better way to do this in C#?
(In case anyone's wondering why I want to do this, it's because I use explicit interface implementations, and calling one of those from within another member function requires a cast to the interface type first, otherwise the compiler can't find the method.)
UPDATE
Another option I came up with is an object extension:
public static class ObjectExtensions
{
[DebuggerStepThrough]
public static T StaticTo<T>(this T o)
{
return o;
}
}
So ((I)c).Doit() could also be c.StaticTo<I>().Doit(). Hmm...probably will still stick with the simple cast. Figured I'd post this other option anyway.
Simply cast it:
(I)c
Edit Example:
var c = new C();
((I)c).MethodOnI();
Write an extension method that uses the trick you mentioned in your UPDATE:
public static class ObjectExtensions
{
public static T StaticCast<T>(this T o) => o;
}
To use:
things.StaticCast<IEnumerable>().GetEnumerator();
If things is, e.g., IEnumerable<object>, this compiles. If things is object, it fails.
// Compiles (because IEnumerable<char> is known at compiletime
// to be IEnumerable too).
"adsf".StaticCast<IEnumerable>().GetEnumerator();
// error CS1929: 'object' does not contain a definition for 'StaticCast'
// and the best extension method overload
// 'ObjectExtensions.StaticCast<IEnumerable>(IEnumerable)'
// requires a receiver of type 'IEnumerable'
new object().StaticCast<IEnumerable>().GetEnumerator();
Why Use a Static Cast?
One common practice during refactoring is to go ahead and make your changes and then verify that your changes have not caused any regressions. You can detect regressions in various ways and at various stages. For example, some types of refactoring may result in API changes/breakage and require refactoring other parts of the codebase.
If one part of your code expects to receive a type (ClassA) that should be known at compiletime to implement an interface (IInterfaceA) and that code wants to access interface members directly, it may have to cast down to the interface type to, e.g., access explicitly implemented interface members. If, after refactoring, ClassA no longer implements IIterfaceA, you get different types of errors depending on how you casted down to the interface:
C-style cast: ((IInterfaceA)MethodReturningClassA()).Act(); would suddenly become a runtime cast and throw a runtime error.
Assigning to an explicitly-typed variable: IInterfaceA a = MethodReturningClassA(); a.Act(); would raise a compiletime error.
Using the static_cast<T>-like extension method: MethodReturningClassA().StaticCast<IInterfaceA>().Act(); would raise a compiletime error.
If you expected your cast to be a downcast and to be verifiable at compiletime, then you should use a casting method that forces compiletime verification. This makes the intentions of the code’s original developer to write typesafe code clear. And writing typesafe code has the benefit of being more verifiable at compiletime. By doing a little bit of work to clarify your intention to opt into typesafety to both other developers, yourself, and the compiler, you magically get the compiler’s help in verifying your code and can catch repercussions of refactoring earlier (at compiletime) than later (such as a runtime crash if your code didn’t happen to have full test coverage).
var c = new C();
I i = c; // statically checked
equals to
I i = new C();
If you're really just looking for a way to see if an object implements a specific type, you should use as.
I i = whatever as i;
if (i == null) // It wasn't
Otherwise, you just cast it. (There aren't really multiple types of casting in .NET like there are in C++ -- unless you get deeper than most people need to, but then it's more about WeakReference and such things.)
I i = (I)c;
If you're just looking for a convenient way to turn anything implementing I into an I, then you could use an extension method or something similar.
public static I ToI(this I #this)
{
return #this;
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
What’s the point of the var keyword?
Use of var keyword in C#
I understand how IEnumerable<...> for a datatype can make the code a little less readable or how nested generics can seem a little daunting. But aside from code readability, are there advantages to using var instead of the explicit type? It seems like by using the explicit type, you'd better convey what the variable is capable of because you know what it is.
If it's a workplace coding standard, I use it for the sake of teamwork. In my own projects however, I prefer to avoid the user of var.
The point of var is to allow anonymous types, without it they would not be possible and that is the reason it exists. All other uses I consider to be lazy coding.
Using var as the iterator variable for a foreach block is more type safe than explicit type names. For example
class Item {
public string Name;
}
foreach ( Item x in col ) {
Console.WriteLine(x.Name);
}
This code could compile without warnings and still cause a runtime casting error. This is because the foreach loop works with both IEnumerable and IEnumerable<T>. The former returns values typed as object and the C# compiler just does the casting to Item under the hood for you. Hence it's unsafe and can lead to runtime errors because an IEnumerable can contain objects of any type.
On the other hand the following code will only do one of the following
Not compile because x is typed to object or another type which does not have a Name field / property
Compile and be guaranteed to not have a runtime cast error while enumerating.
The type of 'x' will be object in the case of IEnumerable and T in the case of IEnumerable<T>. No casting is done by the compiler.
foreach ( var x in col ) {
Console.WriteLine(x.Name);
}
I like it, especially in unit tests, because as the code evolves I only have to fix up the right-hand side of the declaration/assignment. Obviously I also have to update to reflect the changes in usage, but at the point of declaration I only have to make one change.
It produces no meaningful change in the emitted IL. It is merely a code style preference.
I, for one, like it, especially when dealing with types that have long, generic, almost unreadable names such as Dictionary<string, IQueryable<TValue1, TValue2>>[].
The var is just a syntactic sugar. It is always known at compile time what type the variable is. There are no other advantages of using the var keyword.
There aren't any real differences. Some people suggest using the explicit type because it can make maintaining the code easier. However, people that push for var have the stance that "if we use var, we are forced to use good naming conventions".
Of course if you use vars with the intention of having good naming conventions and that breaks down, it's more painful down the road. (IMO)
public IAwesome { string Whatever { get; } }
public SoCool : IAwesome { public string Whatever { get; } }
public HeyHey
{
public SoCool GetSoCool() { return new SoCool(); }
public void Processy()
{
var blech = GetSoCool();
IAwesome ohYeah = GetSoCool();
// Now blech != ohYeah, so var is blech and ohYeah is IAwesome.
}
}
Besides the readability aspect you mentioned, 'var' also has the benefit of reducing the probability that a trivial code change will break other parts of your code. If you rename a type, for example. Or if you switch to a different type that is mostly compatible with the former type (e.g. changing from Foo[] to IEnumerable) you have much less work to do to get your code back to a compilable state.
You can abstract away the mental complexity of the technicalities to focus purely on the problem domain from your model. you have to make sure your variables are named meaningfully tho.