7

Which (if any) is more correct? Why?

string someVariable = (string) someOtherVariable;
string someVariable = someOtherVariable.ToString();
string someVariable = someOtherVariable as string;

I've used all three, but I don't have any preference or understanding why one is better than the other.

Deane
  • 8,269
  • 12
  • 58
  • 108

10 Answers10

10

These are not all examples of casting.

This is a cast:

string someVariable = (string) someOtherVariable;

This is method call:

string someVariable = someOtherVariable.ToString();

And this is a safe cast:

string someVariable = someOtherVariable as string;

The first and third examples are actual casts. The first cast has the potential to throw an InvalidCastException whereas the third example will not throw that exception. That is why the as operator is known as a safe cast.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • If I can't cast someOtherVariable into a string, what will a safe cast do? – Deane Jan 12 '10 at 21:47
  • 3
    @Deane: It will return null instead. – rmac Jan 12 '10 at 21:49
  • 1
    It's worth mentioning that the `ToString` method basically asks someOtherVariable to represent itself as a string and the default implementation (inherited from Object) just returns the class name. As for the "safe cast", `as` tries to pack the value of someOtherVariable into a string-shaped box, and just leaves the box empty if it doesn't fit (i.e. someVariable will be null if someOtherVariable cannot be cast to a string). – Rory Jan 12 '10 at 21:49
  • 1
    That said As-Casting is typically faster than the others: http://www.codeproject.com/KB/cs/csharpcasts.aspx has an example. – ahsteele Jan 12 '10 at 21:50
  • 2
    Using the "as" operator will return null if the type is not one that has been implemented or inherited. Something else that hasn't been mention yet is that the "as" operator will not cause an implicit or explicit conversion, but doing "(type)variable" will do a conversion if needed. – Chris Pitman Jan 12 '10 at 21:51
  • @ahsteele: The referenced article is out-of-date. There is no longer a performance difference (iirc since .NET 2.0). – Dirk Vollmar Jan 12 '10 at 21:53
  • @divo Oh good to know. I was still under the impression that it mattered. And my love affair w/ Stack Overflow deepens. :) – ahsteele Jan 12 '10 at 22:01
7

Here's my article on the subject.

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

As for which one is "most correct", the one that is most correct is the one that has the meaning you intend to convey to the reader of the program.

"ToString()" conveys "this is probably not a string; if it is not, then I wish to obtain from the object a string which represents it."

The "cast" operator conveys either "this is a string, and I am willing to have my program crash if I am wrong", or the opposite, "this is not a string and I want to call a user-defined conversion on this object to string".

The "as" operator conveys "this might be a string and if it isn't, I want the result to be null."

Which of those four things do you mean?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
5

The three do different things -- none are "more correct", it depends on your situation. If you have a bunch of objects that may not be strings, you'd probably use .ToString() (with a null check, if you expect nulls).

If you only care about the non-null strings, but still expect to be receiving non-strings, use an "as" cast, and then ignore the values that come in as null (they were either originally null, or of a non-string type)

if you expect to receive only strings, it is best to use the (string) cast. This expresses the intent best in the code.

object foo = 5;
string str = (string)foo;    // exception
string str = foo as string;  // null
string str = foo.ToString(); // "5"

object foo = "bar";
string str = (string)foo;    // "bar"
string str = foo as string;  // "bar"
string str = foo.ToString(); // "bar"

object foo = null;
string str = (string)foo;    // null
string str = foo as string;  // null
string str = foo.ToString(); // exception
Jimmy
  • 89,068
  • 17
  • 119
  • 137
2

The as keyword is very useful if you think the conversion will fail during an upcast. For instance, if I want to perform the same operation on similar types in a Control list... let's say unchecking all Checkboxes:

foreach (Control ctrl in Controls)
{
    Checkbox box = ctrl as Checkbox;
    if (box != null)
        box.Checked = false;
}

This way, if my list has something else, like a text box or a label, no exception is thrown (as simply sets the variable = null if it fails), and it's very efficient. There is no exception overhead.

Nick
  • 5,875
  • 1
  • 27
  • 38
2

The ideas of CAST and CONVERT should not be confused here. Casting involves viewing an object as if it was another type. Converting involves transforming an object to another type.

If your intention is to CAST to a string, you should use the first or third. (Option depends on what you want to happen in the error condition. See bangoker's answer.)

If your intention is to CONVERT to a string, you should use the second. (Or better, ChaosPandion's modified statement with the trinary operator.) That is because the ToString method's behaviour is defined as converting the object into a string representation.

Community
  • 1
  • 1
jdmichal
  • 10,984
  • 4
  • 43
  • 42
0

This is 100% personal preference here, but for me I use the folowing:

string someVariable = (string) someOtherVariable;

When converting to a child or parent type (eg. NetworkStream->Stream)

string someVariable = someOtherVariable.ToString();

When converting to a new type (int -> string)

And I never use the latter (as string) method, mostly because coming from a C/C++ background I prefer the() and it's a bit more concise.

Timothy Baldridge
  • 10,455
  • 1
  • 44
  • 80
  • Casting to a parent type is implicit so you'd rarely have to perform an explicit cast in that case. Also, I think that "as" is sometimes useful when you are checking for a particular type and null instances at the same time (since "as" returns null if the object is not of the specified type). Ex. You might have a method that takes an optional parameter "sender" of type object (to satisfy an interface requirement) but you are still concerned with its type: Foo x = sender as Foo; if(x != null) x.Bar(); – Michael Petito Jan 12 '10 at 21:53
0

There is a big difference between casting with parenthesis and casting with "as".

Basically, parenthesis will thrown an exception while "as" will return null instead of raising an exception.

More detailed info here

Community
  • 1
  • 1
Padu Merloti
  • 3,219
  • 3
  • 33
  • 44
0
string someVariable = (string) someOtherVariable;

this is your good old normal casting and it will throw an exception if you try to cast something into something it CANNOT be casted (thus some times you need to check if they are castable)

string someVariable = someOtherVariable.ToString();

is not really casting, its executing a method that may come from different places(interfaces) but that ALL objects in C# have, since they inherit from the Object object, which has it. It has a default operation which is giving the name of the type of the object, but you can overload it to print whatever you want your class to print on the ToString method.

string someVariable = someOtherVariable as string;

This is a new c# casting, it will check first if it is castable by using a variable is string first and then doing the casting if it is valid or return null if it is not, so it could be a silent error if you are expecting exceptions, since you should check against null.

Basically

myType as myOtherType 

is the same as:

var something = null;
if(myType is myOtherType)
{
  something = (myType) myotherType;
}

except that as will check and cast in one step, and not in 2.

Francisco Noriega
  • 13,725
  • 11
  • 47
  • 72
0

First of all, you should avoid casting with AS operator. The article linked explains why.

Second, you can use AS operator ONLY if you expect the value not being of the type you cast too. So you will have to check that manually.

Also the obj.ToString() method call is not a casting, it converts object to a string representation (which in case of a string itself is the same string). This can be ovveridden by any class.


So as a general rule I follow this:

  1. Always use (Type) casting.
  2. Use as operator only if object can be of other type than you cast to.
  3. If using as operator - ALWAYS check the result for NULL.
  4. UseToString only in cases when you need to display information about the object.
Dmytrii Nagirniak
  • 23,696
  • 13
  • 75
  • 130
  • 1
    Using your own blog as a point of reference on an opinion is not the best defense. "as" and a null check is faster then a type check then cast. – Matthew Whited Jan 12 '10 at 22:05
  • I am not arguing that AS is faster. I am saying that As+Null check should always be performed. When in reality many devs just forget to check for nulls. For that reason to there is a good practice in place - use explicit casting (brackets) which will perform type check and will throw descriptive error if type-cast has failed. – Dmytrii Nagirniak Jan 13 '10 at 23:28
0

If your question about the best practice for syntax in casting a variable, then I prefer to use next one:

var someVariable = someOtherVariable as string ?? string.Empty;

Off course you can use someVariableDefaultValue instead of string.Empty.

In case if you cast not to string but into the some complex type, then I recommend next syntax, sometimes called the Safe Navigation Operator:

var complexVariable = otherComplexVariable as ComplexType;
if (complexVariable?.IsCondition)
{
   //your code if cast passed and IsCondition is true
}
else
{
   //your code if cast not passed or IsCondition is false
}