This question already has answers here:
Casting value to T in a generic method
(6 answers)
Closed 2 years ago.
I'm writing code that avoids the overhead of Convert.ChangeType(). But I'm getting hung up one one little detail, which is illustrated below.
public void GetValue(out T value)
{
if (typeof(T) == typeof(string))
value = (T)""; // <== Cannot convert 'string' to 'T'
// ...
}
I have a value that I know is of type T, but how can I assign that value to an instance of type T with minimal overhead? I'm really hoping for something fast and simple. Otherwise, I'll scrap my code and use Convert.ChangeType() in a try...catch block.
You need to cast it to object first:
value = (T)(object)"";
Even though you've done a check for type compatibility the compiler doesn't look at this. As far as it's concerned you've got a T and a string which there isn't a direct cast. You have to bounce the string down to an object first (for which there is a direct cast) and then cast to T which as far as the compiler is concerned may fail, but won't because you've already checked the type!
This question already has answers here:
Casting vs using the 'as' keyword in the CLR
(18 answers)
Closed 9 years ago.
How does the "is" operator work in C#?
I have been told that this :
if (x is string)
{
string y = x as string;
//Do something
}
is not as good as this:
string y = x as string;
if (y != null)
{
//Do something
}
Which is better and why?
FxCop issues Warning CA1800 in the first scenario (and not only when using as, but also when using an unchecked cast) as both is and the actual casts require certain type checking operations to determine whether the cast is successful or whether to throw an InvalidCastException.
You might save a few operations by just using as once and then checking the result for null if you are going to use the cast value anyway, rather than checking explicitly with is and then casting anew.
I think second is better cause in first case it will cast object 2 times, first time with is operator and second time in as operator.
while in second case it cast only one time.
The is operator checks if an object can be cast to a specific type or not
like
if (someObj is StringBuilder)
{
StringBuilder ss = someObj as StringBuilder
....
}
The as operator cast an object to a specific type, and returns null if it fails.
like
StringBuilder b = someObj as StringBuilder;
if (b != null) ...
I would use the first approach when more than one type is expected to be stored in x. (You might be passed a string, or a StringBuilder etc). This would allow for non-exception based handling.
If you are always expecting x to hold a certain type of value, then I would use the second option. The check for null is inexpensive and provides a level of validation.
-- Edit --
Wow. After reading some of the comments below, I started looking for more updated information. There is a LOT more to consider, when using as vs is vs (casting). Here are two interesting reads I found.
Does it make sense to use "as" instead of a cast even if there is no null check? and http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx?PageIndex=1#comments
Both of which seem to be well summarized by Jon Skeet's blog. http://www.yoda.arachsys.com/csharp/faq/#cast.as
This question already has answers here:
LINQ .Cast() extension method fails but (type)object works
(3 answers)
Closed 9 years ago.
I recently had a problem using it user-defined casts (cast operator overload) alongside linq's Cast method.
I found a similar question about my problem here at SO and I also found a link that explains it well. My problem is solved.
But something kept me wondering:
Why this doesn't work:
foolist.Cast<bar>(); // throws InvalidCastException
while this works:
foolist.Select(f => (bar)f).ToList(); // works fine
I believe that it's something related to the implementation of each method. If so, couldn't the Cast method have a similar implementation to Select allowing it to be used with user-defined casts (since this is somewhat expected).
Note: I'm not asking why it fails. I'm asking why the Cast method was written in a way that fails.
The reason why is that the Cast method performs the cast in a generic context
IEnumerable<T> Cast<T>(this IEnumerable e) {
foreach (object cur in e) {
return (T)cur;
}
}
The actual casting logic is verified and emitted at this exact point. This point is in a generic function and has no knowledge of the user defined conversions for the type T is eventually instantiated into. All it has access to is standard CLR style conversions.
In the second example you are doing a cast on the real type (not a generic type parameter). Hence the C# compiler has access to all user defined conversions on that object and can insert the most appropriate one.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When to use .First and when to use .FirstOrDefault with LINQ?
What is the point of using the First operator in LINQ, when you could use the FirstOrDefault operator instead?
var q = results.First(); // Error if empty
To respond directly to your specific question (why use First if you can always use FirstOrDefault), there are instances where you cannot use FirstOrDefault, because it loses information! The "default value" is likely a valid element type in the source list. You have no way to distinguish between the first element in the enumeration being null/default vs. there being no elements in the list unless you use First or first check if there are Any elements, which requires double-enumeration.
This is especially true for value-typed enumerables, such as int[]. default(int) is 0, which is also most likely a valid value of the array.
In general, the two methods represent different logical flows. First would be used if not having any elements is "exceptional" (an error), which then want to handle out-of-band in your application. In this scenario, you "expect" to have at least one element. FirstOrDefault returns null on an empty set, which means you need to do additional processing with the returned value. This is similar logic to the Parse vs TryParse methods on int/double/etc. In fact, your question in some ways leads itself to the more general question of why to ever use exceptions.
Since First throws an exception, it lends itself to all of the code-reuse opportunities that exceptions provide. For example, you could do:
try
{
x = arr1.First();
y = arr2.First();
z = arr3.First();
}
catch
{
throw new ArgumentException();
}
To explicitly force an exception to get raised versus performing a null check.
It's the same discussion as Int32.Parse vs. Int32.TryParse. The former throws an exception in case of failure, the latter returns false and the program continues smoothly...
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Casting: (NewType) vs. Object as NewType
In C#, why ever cast reference types when you can use "as"?
Casting can generate exceptions whereas "as" will evaulate to null if the casting fails.
Wouldn't "as" be easier to use with reference types in all cases?
eg:
MyObject as DataGridView
rather than,
(DataGridView)MyObject
Consider the following alternatives:
Foo(someObj as SomeClass);
and:
Foo((SomeClass)someObj);
Due to someObj being of the wrong type, the first version passes null to Foo. Some time later, this results in a NullReferenceException being thrown. How much later? Depends on what Foo does. It might store the null in a field, and then minutes later it's accessed by some code that expects it to be non-null.
But with the second version, you find the problem immediately.
Why make it harder to fix bugs?
Update
The OP asked in a comment: isn't is easier to use as and then check for null in an if statement?
If the null is unexpected and is evidence of a bug in the caller, you could say:
SomeClass c = someObj as SomeClass;
if (c == null)
{
// hmm...
}
What do you do in that if-block? There are two general solutions. One is to throw an exception, so it is the caller's responsibility to deal with their mistake. In which case it is definitely simpler to write:
SomeClass c = (SomeClass)someObj;
It simply saves you writing the if/throw logic by hand.
There is another alternative though. If you have a "stock" implementation of SomeClass that you are happy to use where nothing better is available (maybe it has methods that do nothing, or return "empty" values, etc.) then you could do this:
SomeClass c = (someObj as SomeClass) ?? _stockImpl;
This will ensure that c is never null. But is that really better? What if the caller has a bug; don't you want to help find bugs? By swapping in a default object, you disguise the bug. That sounds like an attractive idea until you waste a week of your life trying to track down a bug.
(In a way this mimics the behaviour of Objective-C, in which any attempt to use a null reference will never throw; it just silently does nothing.)
operator 'as' work with reference types only.
Sometimes, you want the exception to be thrown. Sometimes, you want to try to convert and nulls are OK. As already stated, as will not work with value types.
One definite reason is that the object is, or could be (when writing a generic method, you may not know at coding-time) being cast to a value type, in which case as isn't allowed.
One more dubious reason is that you already know that the object is of the type in question. Just how dubious depends on how you already know that. In the following case:
if(obj is MyType)
DoMyTypeStuff((MyType)obj);
else
DoMoreGeneralStuff(obj);
It's hard to justify using as here, as the only thing it really does is add a redundant check (maybe it'll be optimised away, maybe it won't). At the other extreme, if you are half-way to a trance state with the amount of information you've got in you're brain's paged-in memory and on the basis of that you are pretty sure that the object must be of the type in question, maybe it's better to add in the check.
Another good reason is that the difference between being of the wrong type and being null gets hidden by as. If it's reasonable to be passing in a string to a given method, including a null string, but it's not reasonable to pass in an int, then val as string has just made the incorrect usage look like a completely different correct usage, and you've just made the bug harder to find and potentially more damaging.
Finally, maybe if you don't know the type of the object, the calling code should. If the calling code has called yours incorrectly, they should receive an exception. To either allow the InvalidCastException to pass back, or to catch it and throw an InvalidArgument exception or similar is a reasonable and clear means of doing so.
If, when you write the code to make the cast, you are sure that the cast should work, you should use (DataGridView)MyObject. This way, if the cast fails in the future, your assumption about the type of MyObject will cause an invalid cast exception at the point where you make the cast, instead of a null reference exception at some point later.
If you do want to handle the case where MyObject is not a DataGridView, then use as, and presumably check for it being null before doing anything with it.
tl;dr If your code assumes something, and that assumption is wrong at run-time, the code should throw an exception.
From MSDN (as (C# reference)):
the as operator only performs reference conversions and boxing conversions. The as operator cannot perform other conversions, such as user-defined conversions, which should instead be performed using cast expressions.
Taking into consideration all of the comments, we came across this just the other day and wondered why you would do a direct cast over using the keyword as. What if you want the cast to fail? This is sometimes the desirable effect you want from a cast if you're casting from a null object. You then push the exception up the call stack.
So, if you want something to fail, use a direct cast, if you're okay with it not failing, use the as keyword.
As is faster and doesn't throw exceptions. Therefore it is generally preferred. Reasons to use casts include:
Using as, you can only assign types that are lower in the inheritance tree to ones that are higher. For example:
object o = "abc" as object;
DataGridView d = "abc" as DataGridView // doesn't do anything
DataGridView could create a custom cast that does allow this. Casts are defined on the target type and therefore allow everything, as long as it's defined.
Another problem with as is that it doesn't always work. Consider this method:
IEnumerable<T> GetList<T>(T item)
{
(from ... select) as IEnumerable<T>
}
This code fails because T could also be a Value Type. You can't use as on those because they can never be null. This means you'll have to put a constraint on T, while it is actually unnecesary. If you don't know whether you're going to have a reference type or not, you can never use as.
Of course, you should always check for null when you use the as keyword. Don't assume no exceptions will be thrown just becase the keyword doesn't throw any. Don't put a Try {} Catch(NullReferenceException){} around it, that't unneccesary and bloat. Just assign the value to a variable and check for null before you use it. Never use it inline in a method call.