In an existing application, code is generated to perform a cast, like below: (the types are also generated classes, I provide an example with just object and string)
object o;
string s = (string)o;
When o is of type int, an InvalidCastException is thrown. Therefore, I want to change the code into:
object o;
string s = o as string;
and check later on whether string s is null.
The System.CodeDom is used to perform the code generation. The cast is generated using the CodeCastExpression Class.
I cannot find a way to generate the variable as type way... Can someone help me out? Thanks!
What about using System.ComponentModel.TypeConverter.
It has methods to check whether it CanConvertFrom(Type) and CanConvertTo(Type) and has the "universal" ConvertTo Method which accepts an Object in and gives an Object back:
public Object ConvertTo(
Object value,
Type destinationType
)
Have a look here: http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx
Maybe you want to try this instead:
//For string...
string s = (o == null ? null : o.ToString());
//For int...
int i = (o == null ? 0 : Convert.ToInt32(o));
Maybe you can just put an if statement before so the code would read:
TheType s = null;
if (o is TheType)
s = (TheType)o
This will only work with non-value-types. See this post for information on how to accomplish the "is" operator.
The problem is, the 'as' operator cannot be used with a non reference type.
For example:
public class ConverterThingy
{
public T Convert<T>(object o)
where T : class
{
return o as T;
}
public T Convert<T>(object o, T destinationObj)
where T : class
{
return o as T;
}
}
This should work for most of it. You can do the as conversion from any object to another reference type.
SomeClass x = new ConverterThingy().Convert<SomeClass>(new ExpandoObject());
// x is null
SomeClass x = null;
x = new ConverterThingy().Convert(new ExpandoObject(), x);
// x is null, the type of x is inferred from the parameter
Related
I've seen many people use the following code:
Type t = obj1.GetType();
if (t == typeof(int))
// Some code here
But I know you could also do this:
if (obj1.GetType() == typeof(int))
// Some code here
Or this:
if (obj1 is int)
// Some code here
Personally, I feel the last one is the cleanest, but is there something I'm missing? Which one is the best to use, or is it personal preference?
All are different.
typeof takes a type name (which you specify at compile time).
GetType gets the runtime type of an instance.
is returns true if an instance is in the inheritance tree.
Example
class Animal { }
class Dog : Animal { }
void PrintTypes(Animal a) {
Console.WriteLine(a.GetType() == typeof(Animal)); // false
Console.WriteLine(a is Animal); // true
Console.WriteLine(a.GetType() == typeof(Dog)); // true
Console.WriteLine(a is Dog); // true
}
Dog spot = new Dog();
PrintTypes(spot);
What about typeof(T)? Is it also resolved at compile time?
Yes. T is always what the type of the expression is. Remember, a generic method is basically a whole bunch of methods with the appropriate type. Example:
string Foo<T>(T parameter) { return typeof(T).Name; }
Animal probably_a_dog = new Dog();
Dog definitely_a_dog = new Dog();
Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.
Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal".
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"
Use typeof when you want to get the type at compilation time. Use GetType when you want to get the type at execution time. There are rarely any cases to use is as it does a cast and, in most cases, you end up casting the variable anyway.
There is a fourth option that you haven't considered (especially if you are going to cast an object to the type you find as well); that is to use as.
Foo foo = obj as Foo;
if (foo != null)
// your code here
This only uses one cast whereas this approach:
if (obj is Foo)
Foo foo = (Foo)obj;
requires two.
Update (Jan 2020):
As of C# 7+, you can now cast inline, so the 'is' approach can now be done in one cast as well.
Example:
if(obj is Foo newLocalFoo)
{
// For example, you can now reference 'newLocalFoo' in this local scope
Console.WriteLine(newLocalFoo);
}
1.
Type t = typeof(obj1);
if (t == typeof(int))
This is illegal, because typeof only works on types, not on variables. I assume obj1 is a variable. So, in this way typeof is static, and does its work at compile time instead of runtime.
2.
if (obj1.GetType() == typeof(int))
This is true if obj1 is exactly of type int. If obj1 derives from int, the if condition will be false.
3.
if (obj1 is int)
This is true if obj1 is an int, or if it derives from a class called int, or if it implements an interface called int.
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
This is an error. The typeof operator in C# can only take type names, not objects.
if (obj1.GetType() == typeof(int))
// Some code here
This will work, but maybe not as you would expect. For value types, as you've shown here, it's acceptable, but for reference types, it would only return true if the type was the exact same type, not something else in the inheritance hierarchy. For instance:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
This would print "o is something else", because the type of o is Dog, not Animal. You can make this work, however, if you use the IsAssignableFrom method of the Type class.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
This technique still leaves a major problem, though. If your variable is null, the call to GetType() will throw a NullReferenceException. So to make it work correctly, you'd do:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
With this, you have equivalent behavior of the is keyword. Hence, if this is the behavior you want, you should use the is keyword, which is more readable and more efficient.
if(o is Animal)
Console.WriteLine("o is an animal");
In most cases, though, the is keyword still isn't what you really want, because it's usually not enough just to know that an object is of a certain type. Usually, you want to actually use that object as an instance of that type, which requires casting it too. And so you may find yourself writing code like this:
if(o is Animal)
((Animal)o).Speak();
But that makes the CLR check the object's type up to two times. It will check it once to satisfy the is operator, and if o is indeed an Animal, we make it check again to validate the cast.
It's more efficient to do this instead:
Animal a = o as Animal;
if(a != null)
a.Speak();
The as operator is a cast that won't throw an exception if it fails, instead returning null. This way, the CLR checks the object's type just once, and after that, we just need to do a null check, which is more efficient.
But beware: many people fall into a trap with as. Because it doesn't throw exceptions, some people think of it as a "safe" cast, and they use it exclusively, shunning regular casts. This leads to errors like this:
(o as Animal).Speak();
In this case, the developer is clearly assuming that o will always be an Animal, and as long as their assumption is correct, everything works fine. But if they're wrong, then what they end up with here is a NullReferenceException. With a regular cast, they would have gotten an InvalidCastException instead, which would have more correctly identified the problem.
Sometimes, this bug can be hard to find:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
This is another case where the developer is clearly expecting o to be an Animal every time, but this isn't obvious in the constructor, where the as cast is used. It's not obvious until you get to the Interact method, where the animal field is expected to be positively assigned. In this case, not only do you end up with a misleading exception, but it isn't thrown until potentially much later than when the actual error occurred.
In summary:
If you only need to know whether or not an object is of some type, use is.
If you need to treat an object as an instance of a certain type, but you don't know for sure that the object will be of that type, use as and check for null.
If you need to treat an object as an instance of a certain type, and the object is supposed to be of that type, use a regular cast.
If you're using C# 7, then it is time for an update to Andrew Hare's great answer. Pattern matching has introduced a nice shortcut that gives us a typed variable within the context of the if statement, without requiring a separate declaration/cast and check:
if (obj1 is int integerValue)
{
integerValue++;
}
This looks pretty underwhelming for a single cast like this, but really shines when you have many possible types coming into your routine. The below is the old way to avoid casting twice:
Button button = obj1 as Button;
if (button != null)
{
// do stuff...
return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
// do stuff...
return;
}
Label label = obj1 as Label;
if (label != null)
{
// do stuff...
return;
}
// ... and so on
Working around shrinking this code as much as possible, as well as avoiding duplicate casts of the same object has always bothered me. The above is nicely compressed with pattern matching to the following:
switch (obj1)
{
case Button button:
// do stuff...
break;
case TextBox text:
// do stuff...
break;
case Label label:
// do stuff...
break;
// and so on...
}
EDIT: Updated the longer new method to use a switch as per Palec's comment.
I had a Type-property to compare to and could not use is (like my_type is _BaseTypetoLookFor), but I could use these:
base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);
Notice that IsInstanceOfType and IsAssignableFrom return true when comparing the same types, where IsSubClassOf will return false. And IsSubclassOf does not work on interfaces, where the other two do. (See also this question and answer.)
public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}
Animal dog = new Dog();
typeof(Animal).IsInstanceOfType(dog); // true
typeof(Dog).IsInstanceOfType(dog); // true
typeof(ITrainable).IsInstanceOfType(dog); // true
typeof(Animal).IsAssignableFrom(dog.GetType()); // true
typeof(Dog).IsAssignableFrom(dog.GetType()); // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true
dog.GetType().IsSubclassOf(typeof(Animal)); // true
dog.GetType().IsSubclassOf(typeof(Dog)); // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false
I prefer is
That said, if you're using is, you're likely not using inheritance properly.
Assume that Person : Entity, and that Animal : Entity. Feed is a virtual method in Entity (to make Neil happy)
class Person
{
// A Person should be able to Feed
// another Entity, but they way he feeds
// each is different
public override void Feed( Entity e )
{
if( e is Person )
{
// feed me
}
else if( e is Animal )
{
// ruff
}
}
}
Rather
class Person
{
public override void Feed( Person p )
{
// feed the person
}
public override void Feed( Animal a )
{
// feed the animal
}
}
I believe the last one also looks at inheritance (e.g. Dog is Animal == true), which is better in most cases.
It depends on what I'm doing. If I need a bool value (say, to determine if I'll cast to an int), I'll use is. If I actually need the type for some reason (say, to pass to some other method) I'll use GetType().
The last one is cleaner, more obvious, and also checks for subtypes. The others do not check for polymorphism.
Used to obtain the System.Type object for a type. A typeof expression takes the following form:
System.Type type = typeof(int);
Example:
public class ExampleClass
{
public int sampleMember;
public void SampleMethod() {}
static void Main()
{
Type t = typeof(ExampleClass);
// Alternatively, you could use
// ExampleClass obj = new ExampleClass();
// Type t = obj.GetType();
Console.WriteLine("Methods:");
System.Reflection.MethodInfo[] methodInfo = t.GetMethods();
foreach (System.Reflection.MethodInfo mInfo in methodInfo)
Console.WriteLine(mInfo.ToString());
Console.WriteLine("Members:");
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
Console.WriteLine(mInfo.ToString());
}
}
/*
Output:
Methods:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Members:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Void .ctor()
Int32 sampleMember
*/
This sample uses the GetType method to determine the type that is used to contain the result of a numeric calculation. This depends on the storage requirements of the resulting number.
class GetTypeTest
{
static void Main()
{
int radius = 3;
Console.WriteLine("Area = {0}", radius * radius * Math.PI);
Console.WriteLine("The type is {0}",
(radius * radius * Math.PI).GetType()
);
}
}
/*
Output:
Area = 28.2743338823081
The type is System.Double
*/
I found checking if the type of something is equal to something is done by the following:
variableName.GetType() == typeof(int)
if (c is UserControl) c.Enabled = enable;
You can use "typeof()" operator in C# but you need to call the namespace using System.IO; You must use "is" keyword if you wish to check for a type.
Performance test typeof() vs GetType():
using System;
namespace ConsoleApplication1
{
class Program
{
enum TestEnum { E1, E2, E3 }
static void Main(string[] args)
{
{
var start = DateTime.UtcNow;
for (var i = 0; i < 1000000000; i++)
Test1(TestEnum.E2);
Console.WriteLine(DateTime.UtcNow - start);
}
{
var start = DateTime.UtcNow;
for (var i = 0; i < 1000000000; i++)
Test2(TestEnum.E2);
Console.WriteLine(DateTime.UtcNow - start);
}
Console.ReadLine();
}
static Type Test1<T>(T value) => typeof(T);
static Type Test2(object value) => value.GetType();
}
}
Results in debug mode:
00:00:08.4096636
00:00:10.8570657
Results in release mode:
00:00:02.3799048
00:00:07.1797128
I come from a strong Java background and I am very used to this kind of code:
Object o = foo();
if (o == null) {
bar();
} else {
somethingElse();
}
public Object foo() {
//code....
if (..) {
return Object;
} else {
return null;
But c# does not allow this. I want a function that returns an object if it has been found or return null if there is not such instance. What is the way to go about it in c#?
Have you tried doing this in C#? The code you posted should work exactly the same way in C#, and there's no reason to think that a simple null check would be different.
However, unlike Java, C# also offers a more idiomatic way of handling nulls. C# has the ?? operator, which is fairly similar to the ternary ? operator, but checks for null.
Object o = foo();
Object result = o ?? somethingElse();
That snippet will call foo() and assign it to result if o is NOT null, or call somethingElse() if o is null.
Note that for value types, C# has the concept of nullable types, unlike Java. In Java,
int x = null;
is not valid. It's also not valid in C#, but you can create a nullable int. That means a value type (int in this case) that can also have null as a value.
int? x = null;
That is valid C# code.
I have a List<object> which is a collection of various type of objects.
I am writing a helper method which will return a specific type of object. The helper method will accept type name as string parameter.
Note: I am using 3.5 framework.
If you need to use a string as parameter you can't rely on OfType<T>() extension method. Fortunately it's easy to emulate:
public IEnumerable<object> OfType(this List<object> list, string typeName)
{
return list.Where(x => x != null && x.GetType().Name == typeName);
}
As pointed out by #ChrisSinclair in the comment this solution does not manage conversions, casts and inheritance/interfaces. Casts (because of user defined conversion operators) and conversions (because of TypeConverters and the IConvertible interface) are little bit more tricky. For simple (implicit) casts (like with inheritance and interfaces) you can use this:
public IEnumerable<object> OfType(this List<object> list, string typeName)
{
Type type = Type.GetType(typeName);
return list.Where(x => x != null && type.IsAssignableFrom(x.GetType()));
}
How to perform conversions (even with CUSTOM CONVERSION OPERATORS) at run-time
I found I needed something like the code I posted in this answer but I had to extend it a little bit, here a better implementation that takes care of custom casts and conversions.
Put everything inside a CastExtensions class (or update code if you don't) then declare this small enum for its options:
[Flags]
public enum CastOptions
{
None = 0,
ExcludeNulls = 1,
UseConversions = 2
}
The problem is that C# in general is a statically typed language, it means that almost everything (about types) must be known at compile time (then to perform a cast you have to know type your want to cast to at compile time). This function handles simple cases (like derivation) and more complex ones (interfaces, custom conversion operators - casts - and conversions - when required).
public static IEnumerable<object> OfType(this List<object> list,
string typeName, CastOptions options)
{
Type type = Type.GetType(typeName);
foreach (var obj in list)
{
if (Object.ReferenceEquals(obj, null))
{
if (options.HasFlag(CastOptions.ExcludeNulls))
continue;
yield return obj;
}
var objectType = obj.GetType();
// Derived type?
if (type.IsAssignableFrom(objectType))
yield return obj;
// Should we try to convert?
if (!options.HasFlag(CastOptions.UseConversions))
continue;
// Castable?
object convertedValue = null;
try
{
var method = typeof(CastExtensions)
.GetMethod("Cast", BindingFlags.Static|BindingFlags.NonPublic)
.MakeGenericMethod(type);
convertedValue = method.Invoke(null, new object[] { obj });
}
catch (InvalidCastException)
{
// No implicit/explicit conversion operators
}
if (convertedValue != null)
yield return convertedValue;
// Convertible?
if (options.HasFlag(CastOptions.UseConversions))
{
try
{
IConvertible convertible = obj as IConvertible;
if (convertible != null)
convertible.ToType(type, CultureInfo.CurrentCulture);
}
catch (Exception)
{
// Exact exception depends on the source object type
}
}
}
}
Note that conversion may be or not equivalent to a cast, actually it depends on
the implementation and the exact types involved in the operation (that's why you
can enable or disable this feature through options).
This is a small helper function needed for cast at run-time:
private static T Cast<T>(object obj)
{
return (T)obj;
}
We may emit this code at run-time (I suppose even using expressions but I didn't try) but a small helper method will generate exactly the code we need (conversion from an object to a generic known at run-time type). Note that this cast function doesn't work as expected for value types, for example:
int a = 1;
float a = Cast<float>(a); // Run-time error
This is because (object)1 cannot be converted to anything else than int (this is true for all boxed value types). If you're using C# 4.0 you should change object for parameter obj to dynamic and everything will work as expected (for all types).
Maybe something like that :
var ofTypeTypeA = myList.OfType<TypeA>();
A clean way is to force the user to specify the type as type to avoid loose strings in your application.
Then you could use generics and just use the type you are interested in. That would also allow the caller to skip the cast when using the IEnumerable later.
So instead of this:
List<object> newList = GetOfType(myList, "SomeObject");
// CAST!!
SomeObject someObject = newList[0] as SomeObject;
if (someObject != null)
// use object
you would just do:
IEnumerable<SomeObject> newList = myList.OfType<SomeObject>();
foreach (SomeObject someObject in newList){
// no cast neccessary
This makes it unsensitive in the future if you should rename the class SomeObject (because refactoring tools would pick up on the class name instead of the string)
You can use Enumerable.OfType
var input = new List<object>();
input.Add(1);
input.Add("foo");
var bar = input.OfType<string>();
I guess you need to cast a single object extracted from the list to a strongly-typed object. And not to cast all the list to it. Otherwise use List<MyType>.
So I would go with this: How to cast to a type in C#.
You could use the is operator (or pass the type and check for that also using is). Here is an example of using the is operator:
foreach (var ctl in ControlsList)
{
if (ctl is CheckBox)
//Do this
else if (ctl is TextBox)
//DoThis
}
And by passing the type as string in the parameter, you could do something similar to get the type to test against:
Type t = System.Type.GetType("System.Int32");
I have 2 classes:
class A {
public void A_1(Object b) {
...
Type t = b.GetType();
(t.FullName)b.B_1(); //It doesn`t work! Error in cast
}
....
}
class B {
public void B_1() {
...
}
....
}
A a = new A();
B b = new B();
a.A1(b);
How to cast object correctly?
If you want to cast an object of any type to an object of another type, you do this:
// Will Throw an exception at runtime if it cant be cast.
B newObject = (B)oldObject;
// Will return null at runtime if the object cannot be cast
B newObject = oldObject as B;
// If in a generic method, convert based on the generic type parameter regardless of condition - will throw an exception at runtime if it cant be cast
B newObject = (T)Convert.ChangeType(oldObject, typeof(T))
Your syntax is off; you don't convert from the fullname to the object, you simply convert from the type symbol.
double x = (double)40;
ClassB anotherInstance = (ClassB)someOtherInstance;
What you're trying to do is basically:
Foo myFoo = ("Foo")myObject;
That definitely will not work in C#. When you cast in C#, the compiler emits code that does the cast, it needs to know what it's casting from and to, in order to write that code. A string does not help the compiler out here.
As others have pointed out, what you want to do doesn't seem like you really need to (unless this is just a contrived example). If you really want to do this, you'll need to work with a more dynamic language than C#, or find a C# friendly way of accomplishing this.
Are you sure you didn't mean to do (B)b.B_1()?
C# has a static type-system, i.e. all types must be known at compile-time (modulo reflection). So, casting to a type that is only known at run-time makes no sense. Specify the type explicitly:
public void A_1(object obj)
{
...
B b = (B)obj;
b.B_1();
// or
((B)obj).B_1();
}
You can also do this:
class A {
public void A_1(Object b) {
...
if (b is B)
{
((B)b).B_1();
}
}
....
}
Type.FullName is just a string; it's not a type. Use this instead: ((B)b).B_1(); Also, using GetType() is a way to get the type of an object dynamically, but casting is only possible or useful when the target type is known at compile time (not dynamic at all). In order to cast, simply refer to the type directly in a pair of parentheses. Don't attempt to obtain or use an object of type Type.
HI!
Here is my case: I have some value type which is wrapped into another type with appropriate implicit converters. If I cast wrapped type to an object and then try to get original value I can do that in two-step cast only.
If simplified my code is as follows:
public enum MyEnum : int
{
First,
Second
}
public class Test<T>
{
public Test(T val)
{
Value = val;
}
private T Value { get; set; }
public static implicit operator T(Test<T> m)
{
return m.Value;
}
public static implicit operator Test<T>(T m)
{
var res = new Test<T>(m);
return res;
}
}
static void Main()
{
object res = new Test<MyEnum>(MyEnum.First);
Console.WriteLine((MyEnum)(Test<MyEnum>)res);
Console.WriteLine((MyEnum)res);
}
First "Console.WriteLine" works OK. Second one fails.
Is there any way I can modify this behavior and get it working without double casting?
UPDATE 1
I must use object to value cast (in real application I have to cast ComboBox.SelectedItem property and I do not want to add extra property to ComboBox, because I'll have to change my UI interaction code everywhere).
UPDATE 2
Implicit conversions to and from System.Object are not allowed.
UPDATE 3
Updated my sample code to reflect the whole problem.
Don't use object that way. Write your first line like this instead:
Test res = new Test(1);
If you must have it in an object first, remember that all the compiler knows about it at this point is that it's an object, and nothing more. You, as the programmer, have additional information about what you expect this object to be, but for the compiler to take advantage of that information you have to put it into your code somewhere.
Update:
I'm glad I was able to find this again, because this almost-very-timely article by Eric Lippert, who works on the C# language design, went up this morning and explains the problem in depth:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
If you want to simplify casting and not care performance effect, then create extension method.
public static T To<T>(this object obj) {
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
MethodInfo method = methods.FirstOrDefault(mi => (mi.Name == "op_Implicit" || mi.Name == "op_Explicit") && mi.ReturnType == typeof(T));
if (method == null)
throw new ArgumentException();
return (T)method.Invoke(null, new[] { obj });
}
Usage
Console.WriteLine(res.To<MyEnum>());
Instead of adding implicit operators, consider implementing IConvertible. You only need to implement the ToInt32 method, the others are meaningless and you can throw the InvalidCastException in the other methods.
After that, you can use Convert.ToInt32() method to convert your object in one step.
or even
var res = new Test(1);
Your local variable res is always of type object; so the line that isn't working is trying to convert an object, that isn't an int, to an int, which can't be done. Same as this fails:
object d = 5.5d;
Console.WriteLine((int)d);
EDIT:
Perhaps a pattern that might help is something like this:
if (res.GetType() == typeof(Test))
{
Console.WriteLine((int)(Test)res);
}
else
{
Console.WriteLine((int)res);
}
It's a very localized solution to your problem, but perhaps it will work for you.
While the error is due to res being of type object, I would make the Test->int operator explicit...