By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,106 Members | 2,335 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,106 IT Pros & Developers. It's quick & easy.

Type conversion Syntax

P: n/a
Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something more
profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;

x = (MySpecificType) someObject;
Thanks.
Aug 5 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Smithers wrote:
Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something more
profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;

x = (MySpecificType) someObject;
Thanks.

One important difference is that the first one will give you a
conversion error if someObject cannot be converted to a MySpecificType
at compile time. The second one will always compile but will throw a
run-time error if someObject cannot be cast to a MySpecificType.

When you know that at compile-time that someObject is of type (or a type
derived from) MySpecificType then use the first syntax. If you don't
know until run-time whether someObject will be of type (or a type
derived from) MySpecificType type then use the second syntax.
--
-glenn-
Aug 5 '07 #2

P: n/a
Smithers wrote:
Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something more
profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;
This will attemt to cast the reference, and if it's not possible, it
will put a null reference in the variable x.

Use this if you aren't certain what the actual type is, and check if the
reference is null to find out if the casting was possible or not.
x = (MySpecificType) someObject;
This will attemt to cast the reference, and it it's not possible, it
will throw an exception.

Use this if you are certain what the actual type is.

--
Göran Andersson
_____
http://www.guffa.com
Aug 5 '07 #3

P: n/a
GlennDoten wrote:
Smithers wrote:
>Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something
more profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;

x = (MySpecificType) someObject;
Thanks.

One important difference is that the first one will give you a
conversion error if someObject cannot be converted to a MySpecificType
at compile time.
No, it won't.
The second one will always compile but will throw a
run-time error if someObject cannot be cast to a MySpecificType.

When you know that at compile-time that someObject is of type (or a type
derived from) MySpecificType then use the first syntax. If you don't
know until run-time whether someObject will be of type (or a type
derived from) MySpecificType type then use the second syntax.
That's completely backwards.

--
Göran Andersson
_____
http://www.guffa.com
Aug 5 '07 #4

P: n/a
Göran Andersson wrote:
GlennDoten wrote:
>Smithers wrote:
>>Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something
more profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;

x = (MySpecificType) someObject;
Thanks.

One important difference is that the first one will give you a
conversion error if someObject cannot be converted to a MySpecificType
at compile time.

No, it won't.
Göran, look at this code:

public class MySpecificType { }
public class MySpecificType2 : MySpecificType { }
public class FooTester
{
public void A()
{
Version v = new Version();
Random r = new Random();
Random r2 = (Random)v;
Random r3 = v as Random;

object o = new object();

MySpecificType x = o as MySpecificType;
MySpecificType y = (MySpecificType)o;

MySpecificType x2 = o as MySpecificType2;
MySpecificType y2 = (MySpecificType2)o;
}
}

On the r2 line, C# gives this error message: "Cannot convert type
'System.Version' to 'System.Random' via a built-in conversion".

On the r3 line, C# gives this error message: "Cannot convert type
'System.Version' to 'System.Random'".

I always thought that C# would let these lines compile and give a
run-time error, but the compiler's smarter than I thought (maybe it's
something new in C# 2.0). The x line compiles but gives this run-time
error: "Unable to cast object of type 'System.Object' to type
'Console_Playground.MySpecificType'".

I think we're both right, and that it depends on whether the compiler
can figure out the type compatibility fully at compile-time or not.
>The second one will always compile but will throw a run-time error if
someObject cannot be cast to a MySpecificType.
You're right; I'm wrong here. I did believe that "as" would always
compile until I tried the r3 line above (at your prompting).
>When you know that at compile-time that someObject is of type MySpecificType (or a
type derived from) MySpecificType then use the first syntax. If you
don't know until run-time whether someObject will be of type (or a
type derived from) MySpecificType type then use the second syntax.

That's completely backwards.
Not quite, I don't think. Although to be clearer I should have said this:

"then use[STRIKE "USE"] the first syntax [ADD "CAN BE USED"]". Though
typically I would use the cast syntax. And I use this pattern all the time:

MySpecificType x = o as MySpecificType;
if (x == null)
{
// x isn't of MySpecificType or doesn't it's type doesn't derive
// from MySpecificType.
}

Sorry if I wasn't clear about that.

Assuming that Smithers means this:

MySpecificType x = someObject as MySpecificType;
MySpecificType x = (MySpecificType) someObject;

and also that Smithers means that someObject is is of type
MySepcificType or a class that derives from MySpecific type. However,
since what he posted is a little ambiguous (he doesn't specify what the
type of x is) I may well be reading his question differently than you
and/or what he means, and maybe the two assumptions I just mentioned
aren't what he intended, but that's the way I read he question. Maybe
Smithers will clarify for us.

The bottom line is the first variant (again, assuming these two
assumptions) is useful when you don't want an exception throw at
run-time and will check the variable to see if it is null or not, and
the second variant is useful when you pretty much now the type of the
variable being cast and if you don't know 100% you don't mind an
exception being thrown at run-time.

--
-glenn-
Aug 5 '07 #5

P: n/a
RE:
<< Maybe Smithers will clarify for us. >>

Gladly - and thanks for the good information so far. The big picture is that
I'm writing an application that is extensible via a plug-in architecture
(thus the use of Activator.CreateInstance() and the subsequent need to
convert to a specific type).

Here is the relevant code. Notice Lines 7 and 8 provide the alternative
conversion syntax in question.

1 private List<CompanyNameHere.CommonInstallerTypes.Installe r>
m_InstallerInstances;
2 Type installerTypeReference = null;
3 System.Reflection.Assembly loadedAssembly =
System.Reflection.Assembly.LoadFile(pathToAssembly );
4 installerTypeReference =
loadedAssembly.GetType(currentInstaller.ClassName) ;
5 if (installerTypeReference != null)
6 {
7 installerInstance = (CompanyNameHere.CommonInstallerTypes.Installer)
Activator.CreateInstance(installerTypeReference);
8 // installerInstance = Activator.CreateInstance(installerTypeReference)
as CompanyNameHere.CommonInstallerTypes.Installer;
9 m_InstallerInstances.Add(installerInstance);
10 }
Thanks for the great dialog. It is very helpful. You can see I'm wanting to
understand this and not simply "get it to work".

-"Smithers"
Aug 5 '07 #6

P: n/a
Smithers wrote:
RE:
<< Maybe Smithers will clarify for us. >>

Gladly - and thanks for the good information so far. The big picture is that
I'm writing an application that is extensible via a plug-in architecture
(thus the use of Activator.CreateInstance() and the subsequent need to
convert to a specific type).

Here is the relevant code. Notice Lines 7 and 8 provide the alternative
conversion syntax in question.

1 private List<CompanyNameHere.CommonInstallerTypes.Installe r>
m_InstallerInstances;
2 Type installerTypeReference = null;
3 System.Reflection.Assembly loadedAssembly =
System.Reflection.Assembly.LoadFile(pathToAssembly );
4 installerTypeReference =
loadedAssembly.GetType(currentInstaller.ClassName) ;
5 if (installerTypeReference != null)
6 {
7 installerInstance = (CompanyNameHere.CommonInstallerTypes.Installer)
Activator.CreateInstance(installerTypeReference);
8 // installerInstance = Activator.CreateInstance(installerTypeReference)
as CompanyNameHere.CommonInstallerTypes.Installer;
9 m_InstallerInstances.Add(installerInstance);
10 }
Both will work. You might use casting--as in line 7--if you were sure
that the ClassName variable always specified the name of a type that is
of type Installer, or a type that derives from type Installer. But even
if the type specified by ClassName were not such a type the code would
still work, it would just throw an exception when line 7 executes. This
may be perfectly acceptable behavior so long as your callers know to
trap for this potential exception and recover accordingly.

Line 8 would work just as well, but typically you would use it if you
had a corresponding line 8a that did something like this:

if (installInstance == null) { /* Handle the incorrect type. */ }

But without such a check then it doesn't matter whether you use a cast
(which will throw an exception if the wrong type is created) or whether
you use the "as" keyword (which will not throw an exception but will
return a null if a wrong type is created).

So which one you use depends on how you want this code to behave.
Personally, I use a cast when creating a "late-bound" object like this
because I know that the type name specified in the ClassName variable is
going to specify a proper type, and if it doesn't I'll catch that bug
during testing. Though you can't always make that assumption, in which
case I'd probably still just wrap a "try" around the cast. Another
pattern I use for this type of code is to replace your line 7 with
something like this:

object instance = Activator.CreateInstance(installerTypeReference);
Debug.Assert(instance is Installer);
installerInstance = (Installer)instance;

Make sense?
Thanks for the great dialog. It is very helpful. You can see I'm wanting to
understand this and not simply "get it to work".
Same thing here!

--
-glenn-
Aug 5 '07 #7

P: n/a
Yes - it all makes sense... exactly the sort of perspective I was looking
for. Thank you very much.

-"Smithers"


"GlennDoten" <gd****@gmail.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Smithers wrote:
>RE:
<< Maybe Smithers will clarify for us. >>

Gladly - and thanks for the good information so far. The big picture is
that I'm writing an application that is extensible via a plug-in
architecture (thus the use of Activator.CreateInstance() and the
subsequent need to convert to a specific type).

Here is the relevant code. Notice Lines 7 and 8 provide the alternative
conversion syntax in question.

1 private List<CompanyNameHere.CommonInstallerTypes.Installe r>
m_InstallerInstances;
2 Type installerTypeReference = null;
3 System.Reflection.Assembly loadedAssembly =
System.Reflection.Assembly.LoadFile(pathToAssembl y);
4 installerTypeReference =
loadedAssembly.GetType(currentInstaller.ClassName );
5 if (installerTypeReference != null)
6 {
7 installerInstance =
(CompanyNameHere.CommonInstallerTypes.Installer )
Activator.CreateInstance(installerTypeReference );
8 // installerInstance =
Activator.CreateInstance(installerTypeReference ) as
CompanyNameHere.CommonInstallerTypes.Installer;
9 m_InstallerInstances.Add(installerInstance);
10 }

Both will work. You might use casting--as in line 7--if you were sure that
the ClassName variable always specified the name of a type that is of type
Installer, or a type that derives from type Installer. But even if the
type specified by ClassName were not such a type the code would still
work, it would just throw an exception when line 7 executes. This may be
perfectly acceptable behavior so long as your callers know to trap for
this potential exception and recover accordingly.

Line 8 would work just as well, but typically you would use it if you had
a corresponding line 8a that did something like this:

if (installInstance == null) { /* Handle the incorrect type. */ }

But without such a check then it doesn't matter whether you use a cast
(which will throw an exception if the wrong type is created) or whether
you use the "as" keyword (which will not throw an exception but will
return a null if a wrong type is created).

So which one you use depends on how you want this code to behave.
Personally, I use a cast when creating a "late-bound" object like this
because I know that the type name specified in the ClassName variable is
going to specify a proper type, and if it doesn't I'll catch that bug
during testing. Though you can't always make that assumption, in which
case I'd probably still just wrap a "try" around the cast. Another pattern
I use for this type of code is to replace your line 7 with something like
this:

object instance = Activator.CreateInstance(installerTypeReference);
Debug.Assert(instance is Installer);
installerInstance = (Installer)instance;

Make sense?
>Thanks for the great dialog. It is very helpful. You can see I'm wanting
to understand this and not simply "get it to work".

Same thing here!

--
-glenn-

Aug 5 '07 #8

P: n/a
This is still not quite right.

the as operator is a reference converter. This means it will convert an
object reference from one type to another based on the rules of polymorphism.
e.g
Imagin you have this object hierachy:
System.Object
MyClassA
MyClassB
MyClassC
MyClassD

So as MyClassA is at the same level as MyClassB this will fail as you cant
point to an instance of MyClassA with a reference of type MyClassB

MyClassA inst = new MyClassA();
MyClassB inst2 = isnt as MyClassB();

This However will work as the rules of polymorphism allow this
Object inst = new MyClassC();
MyClassB inst2 = isnt as MyClassB();
MyClassC inst3 = isnt2 as MyClassC();

This however will fail:

Object inst = new MyClassC();
MyClassD inst3 = isnt2 as MyClassD();

as an instance of MyClassC cant be made more special.
As you can see the 'as' operator works solely on the reference and leaves
the actual instance untouched in all cases. so the reference returned is to
the same memory location as the original but it a different type.

Casting is a little different, the rules above will apply the same way for
casting

BUT

you can add implicit and explicit conversion functions to make casting work
for completly different types. Castign is used this wayto make a different
instance of a different class which is a conversion of the original.

This allows this to work

int a = 1;
double b = (double)a;

int and double are unrelated classes but have conversion functions to allow
you to convert one to the other. In the above case, the memory rerence of b
and a are different (I know this is the case as much to the stack based
nature of them but its the same with reference types and their members).

Hopefully this highlights the difference between the 2.

as = pointer conversion only
(cast) = automatic pointer conversion for reference types or object
conversion for all supporting types.
The other difference is 'as' doesnt throw an expcetion but returns a null if
it fails, therefore it only works for reference types. (casting) throws an
exception on failure and cant be used on value types too.

The compiler support for detecting improper conversions is just MS being
clever. If the compiler can detect a garunteed failure it will throw an
error. The same as writing int i = 10/0; throws a divide by zero exception.
Hope this helps to clarify

--
Ciaran O''Donnell
http://wannabedeveloper.spaces.live.com
"Göran Andersson" wrote:
Smithers wrote:
Are there any important differences between the following two ways to
convert to a type?... where 'important differences' means something more
profound than a simple syntax preference of the developer.

x = someObject as MySpecificType;

This will attemt to cast the reference, and if it's not possible, it
will put a null reference in the variable x.

Use this if you aren't certain what the actual type is, and check if the
reference is null to find out if the casting was possible or not.
x = (MySpecificType) someObject;

This will attemt to cast the reference, and it it's not possible, it
will throw an exception.

Use this if you are certain what the actual type is.

--
Göran Andersson
_____
http://www.guffa.com
Aug 6 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.