Casting: (NewType) vs. Object as NewType
The former will throw an exception if the source type can't be cast to the target type. The latter will result in sc2 being a null reference, but no exception.
[Edit]
My original answer is certainly the most pronounced difference, but as Eric Lippert points out, it's not the only one. Other differences include:
- You can't use the 'as' operator to cast to a type that doesn't accept 'null' as a value
- You can't use 'as' to convert things, like numbers to a different representation (float to int, for example).
And finally, using 'as' vs. the cast operator, you're also saying "I'm not sure if this will succeed."
Should I use (ObjectType) or 'as ObjectType' when casting in c#?
If you wish to avoid any InvalidCastExceptions
use
MyObjectType senderAsMyType = sender as MyObjectType;
otherwise use
MyObjectType senderAsMyType = (MyObjectType)sender;
if an InvalidCastException
represents a true exceptional situation in your application.
As for performance, I would contend that you would find no discernible difference between the two different kinds of casting. I was interested though so I used Jon Skeet's BenchmarkHelper and achieved results that confirmed my suspicions:
Test:
using System;
using BenchmarkHelper;
class Program
{
static void Main()
{
Object input = "test";
String output = "test";
var results = TestSuite.Create("Casting", input, output)
.Add(cast)
.Add(asCast)
.RunTests()
.ScaleByBest(ScalingMode.VaryDuration);
results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
results.FindBest());
}
static String cast(Object o)
{
return (String)o;
}
static String asCast(Object o)
{
return o as String;
}
}
Output:
============ Casting ============
cast 30.021 1.00
asCast 30.153 1.00
What is difference between normal typecasting and using “AS” keyword
Using as
will fail gracefully if the object is the wrong type, and the resulting value will be null, where a normal cast would throw an InvalidCastException:
object x = new object();
string y = x as string; // y == null
string z = (string)x; // InvalidCastException
What is the difference between object as type and ((type)object) ?
var myString = myObject as string;
It only checks the runtime type of myobject
. If its string
, only then it cast as string
, else simply returns null
.
var myString = (string)myObject;
This also looks for implicit
conversion to string from the source type. If neither the runtime type is string
, nor there is implicit
conversion, then it throws exception.
Read Item 3: Prefer the is
or as
Operators to Casts from Effective C# by Bill Wagner.
Different Cast Types in C#
A cast can do three things:
- Perform a user-defined conversion
- Perform an unboxing conversion
- Perform a reference conversion
An as
operation is almost always a reference conversion, the only exception being unboxing to a nullable type:
object x = "hello";
int? y = x as int?; // y is null afterwards
Then there's the behaviour with conversions which fail at execution time. So the differences are:
- Casts performing reference conversions or unboxing will throw
InvalidCastException
on failure;as
will result in the null value of the target type instead - Casts can perform user-defined conversions;
as
can't - Casts can unbox to non-nullable value types;
as
can only be used for unboxing if the target type is a nullable value type
What is the difference between TypeVar and NewType?
The two concepts aren't related any more than any other type-related concepts.
In short, a TypeVar
is a variable you can use in type signatures so you can refer to the same unspecified type more than once, while a NewType
is used to tell the type checker that some values should be treated as their own type.
Type Variables
To simplify, type variables let you refer to the same type more than once without specifying exactly which type it is.
In a definition, a single type variable always takes the same value.
# (This code will type check, but it won't run.)
from typing import TypeVar, Generic, List, Tuple
# Two type variables, named T and R
T = TypeVar('T')
R = TypeVar('R')
# Put in a list of Ts and get out one T
def get_one(x: List[T]) -> T: ...
# Put in a T and an R, get back an R and a T
def swap(x: T, y: R) -> Tuple[R, T]:
return y, x
# A simple generic class that holds a value of type T
class ValueHolder(Generic[T]):
def __init__(self, value: T):
self.value = value
def get(self) -> T:
return self.value
x: ValueHolder[int] = ValueHolder(123)
y: ValueHolder[str] = ValueHolder('abc')
Without type variables, there wouldn't be a good way to declare the type of get_one
or ValueHolder.get
.
There are a few other options on TypeVar
. You can restrict the possible values by passing in more types (e.g. TypeVar(name, int, str)
), or you can give an upper bound so every value of the type variable must be a subtype of that type (e.g. TypeVar(name, bound=int)
).
Additionally, you can decide whether a type variable is covariant, contravariant, or neither when you declare it. This essentially decides when subclasses or superclasses can be used in place of a generic type. PEP 484 describes these concepts in more detail, and refers to additional resources.
NewType
A NewType
is for when you want to declare a distinct type without actually doing the work of creating a new type or worry about the overhead of creating new class instances.
In the type checker, NewType('Name', int)
creates a subclass of int
named "Name."
At runtime, NewType('Name', int)
is not a class at all; it is actually the identity function, so x is NewType('Name', int)(x)
is always true.
from typing import NewType
UserId = NewType('UserId', int)
def get_user(x: UserId): ...
get_user(UserId(123456)) # this is fine
get_user(123456) # that's an int, not a UserId
UserId(123456) + 123456 # fine, because UserId is a subclass of int
To the type checker, UserId
looks something like this:
class UserId(int): pass
But at runtime, UserId
is basically just this:
def UserId(x): return x
There's almost nothing more than that to a NewType
at runtime. As of Python 3.8.1, its implementation is almost exactly as follows:
def NewType(name, type_):
def identity(x):
return x
identity.__name__ = name
return identity
difference between in-front type conversion and as conversion
Per http://msdn.microsoft.com/en-us/library/cscsdfbt%28v=vs.71%29.aspx (emphasis mine):
The as operator is like a cast except that it yields null on
conversion failure instead of raising an exception. More formally, an
expression of the form:expression as type
is equivalent to:
expression is type ? (type)expression : (type)null
except that expression is evaluated only once.
C# difference between casting and as?
as
will never throw a InvalidCastException
. Instead, it returns null if the cast fails (which would give you a NullReferenceException
if obj
in your example were not a string
).
Related Topics
How to Send Emails Through Ssl Smtp with the .Net Framework
At the End of an Async Method, Should I Return or Await
Oledbcommand Parameters Order and Priority
Adding Multiple Parameterized Variables to a Database in C#
How to Set a Property Value with Reflection
Xaml Binding Not Working on Dependency Property
How to Ignore JSONproperty(Propertyname = "Somename") When Serializing JSON
Format Excel Column to Decimal Doing Export from C#
What Is [Serializable] and When Should I Use It
Using Linq to Concatenate Strings
Handling Warning for Possible Multiple Enumeration of Ienumerable
How to Get Client Ip Address in ASP.NET Core
Headless Browser for C# (.Net)
Capture a Keyboard Keypress in the Background
Best Practice to Return Errors in ASP.NET Web API