class TestClass
{
public void Test()
{
//which is faster?
object o1 = MethodRequiringType(typeof(TestClass));
object o2 = MethodRequiringType(this.GetType());
//which is better?
//does it matter?
}
public object MethodRequiringType(Type t)
{
return new { };
}
}
A quick google search revealed this:
GetType is a call that is made at
runtime on an instance of an object.
typeof() is resolved to a call at
runtime, but loads the type from the
token for the type. They probably
resolve to the same call, it's just
that GetType requires an instance. If
I didn't need the instance, I would
use typeof.
and also:
Also be aware that GetType is virtual,
and gives you the type of the object,
not the declared type of the
reference. That is:
Object o = new String();
typeof(o) Object type
o.GetType() String type
Worry about correctness before performance. If there are any classes derived from TestClass, you won't get the same result.
I've actually measured this difference for a lecture I once gave (on reflection and optimization).
Bottom line: if you plan on calling that line several billion times, you'll save a second using the typeOf() instead of the GetType()
Related
Consider following code
using System.Reflection;
public class Sample {
private class User {
public string Name;
}
private List<User> Users = new List<User> {
new User() { Name = "Alice" },
new User() { Name = "Bob" }
};
}
var sample = new Sample();
var usersOfSample = typeof(Sample).GetField("Users", BindingFlags.Instance |
BindingFlags.NonPublic).GetValue(sample);
With reflection, I can get the value of Users, while it is a List of a private class. Now I want to call List.Clear() on users.
My first idea is convert it into dynamic. However, following code does not work as my expectation.
dynamic usersOfSampleDyn = (usersOfSample as dynamic);
usersOfSampleDyn.Clear();
It throws a RuntimeBinderException.
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'Clear'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
at MyCode
Later I try this code in C# Interactive, it says
'object' does not contain a definition for 'Clear'
+ System.Dynamic.UpdateDelegates.UpdateAndExecute1<T0, TRet>(System.Runtime.CompilerServices.CallSite, T0)
Using reflection to call this method works, as following
usersOfSample.GetType().GetMethod("Clear").Invoke(usersOfSample, new object[0]);
Here is my question:
1. Why I can't call Clear() when cast usersOfSample into dynamic?
1.1 During runtime, is usersOfSampleDyn resolved as a List<T> or a object { List<T> }?
1.2 If usersOfSampleDyn was resolved as a object { List<T> }, how to convert it into List<T> or anything I can call Clear() on?
Note: T is private.
2. What's the correct way to call a public List method on object { List<InaccessibleClass> }?
Why I can't call Clear() when cast usersOfSample into dynamic?
because
1.1 During runtime, is usersOfSampleDyn resolved as a List<T> or a object { List<T> }?
it's object {List<T>}.
Edit:
The reason dynamic treats the object as object is that dynamic will be treated as the most derived type that is accessible to where it is called.
as mentioned in Jon Hanna's comment.
1.2 If usersOfSampleDyn was resolved as a object { List<T> }, how to convert it into List or anything I can call Clear() on?
List<T> implements the non-generic IList, simply cast to it:
((IList)usersOfSample).Clear();
What's the correct way to call a public List method on object { List<InaccessibleClass> }?
You don't. If the class in inaccessible it was done that way for a reason. Change the object visibility if it is your own code, otherwise don't muck around in internal state of external code, it can break at any point and have unintended and hard to debug side effects.
But if you really need to it's reflection or casting to IList.
I have a generic method
public async Task Save<T>(T aggregate) where T : AggregateRoot
From this method I call another generic method
var indexRegistrations = IndexRegistrar.GetAll<T>();
Now in this second generic method, I want to get the real type of T, which is a subtype of AggregateRoot:
public static List<IndexRegistration> GetAll<T>() where T : AggregateRoot
{
return _register.FindAll(r => r.aggregateType == typeof(T));
}
However, the typeof(T) always returns AggregateRoot.
How can I get the real type (=subtype of AggregateRoot) of T?
typeof(T) is correct here.
I tested your case, and typeof(T) always returns the "true" class, not just the type requirement.
public class BaseClass { }
public class DerivedClass: BaseClass { }
public class GenericClass<T> where T : BaseClass
{
public string TypeOf = typeof(T).ToString();
}
public class GenericSuperClass<T> where T : BaseClass
{
public GenericClass<T> Sub = new GenericClass<T>();
}
static void Main(string[] args)
{
Console.WriteLine("1 - " + (new GenericClass<BaseClass>()).TypeOf);
Console.WriteLine("2 - " + (new GenericClass<DerivedClass>()).TypeOf);
Console.WriteLine("3 - " + (new GenericSuperClass<BaseClass>()).Sub.TypeOf);
Console.WriteLine("4 - " + (new GenericSuperClass<DerivedClass>()).Sub.TypeOf);
Console.ReadLine();
}
The output:
1 - BaseClass
2 - DerivedClass
3 - BaseClass
4 - DerivedClass
Note that I've simplified the classnames from the values that are actually returned (e.g Sandbox.TestConsole.Program+DerivedClass).
This directly contradicts your claim that you only ever get the base type (AggregateRoot, in your case).
Reflection is an exception to this.
I can think of one exception to this: when your type is only defined at runtime (e.g. generated from a type name (String)).
However, as this StackOverflow answer explains, generics are intended to provide compile time type safety.
It's not impossible to use reflection to instantiate a generic class at runtime. But when you do so, you are inherently preventing the validity of information (e.g. type names) that are decided at compile-time.
MSDN's page on typeof implicitly states that the return value of typeof is the compile-time type.
Combining these two facts, this means that when you use reflection (i.e. deciding the type at runtime), you cannot rely on typeof (as this returns the compile time type).
The linked MSDN page also mentions how to find the runtime type:
To obtain the run-time type of an expression, you can use the .NET Framework method GetType, as in the following example:
int i = 0;
System.Type type = i.GetType();
However, do note that the GetType() method is only available on an instantiated object, not on a generic type parameter. Generic type parameters are not really types, they are much closer to "type placeholders".
You will need either pass the type as a parameter, or an instantiated object (of the appropriate type).
Conclusion:
If you are using types that are known at compile time, then you can simply use typeof(T), as my example has shown.
If you are deciding the type on runtime using reflection, then you cannot rely on the information provided by typeof(T), and will therefore be required to supply the type. Either you supply it as a Type parameter, or you supply it via an instantiated object, whose runtime type can accurately be tested using the GetType() method.
However, if you are already deciding the type on runtime, then you are better off passing the type itself as a parameter. If you're using reflection here, that means that you must at some point have known which type you wanted to use. Therefore, simply pass that known type as a parameter, which you can then use for your subsequent business logic.
I cannot think of a single scenario in which you aren't either (a) using a type that is known at compile time, nor (b) aware (at runtime) of the type you've decided to use.
As #Flater answer stated, typeof is valid is this case, unless when you instanciated these objects you did not know their types.
So this solution will work for types instanciated at run-time. It will also work if you knew the type at compile time, but it is more complicated and adds complexity.
A solution would be to be able to have an instance of your type, in order to call GetType() on that instance, this would give you the lowest inheriting type of the object.
So, to get an instance, either you change your function and ask for an object to be passed along:
public static List<IndexRegistration> GetAll<T>(T instance) where T : AggregateRoot
{
return _register.FindAll(r => r.aggregateType == instance.GetType());
}
Either you create an instance at run-time, and retrieve the type. This require that you mark the generic type as having a parameterless constructor:
public static List<IndexRegistration> GetAll<T>() where T : AggregateRoot, New()
{
T instance = new T();
return _register.FindAll(r => r.aggregateType == instance.GetType());
}
There is a similar answer for your question:
when-and-where-to-use-gettype-or-typeof.
Generally typeof operator checks for a known at compile-time type. So it will always be AggregateRoot in your case.
To match T itself together with all its inheritors use IsAssignableFrom reflection method, instead of type object comparision:
public static List<IndexRegistration> GetAll<T>() where T : AggregateRoot
{
return _register.FindAll(r => typeof(T).IsAssignableFrom(r.aggregateType));
}
I'm looking for how to get compile time type of a variable for debugging purposes.
The testing environment can be reproduced as simply as:
object x = "this is actually a string";
Console.WriteLine(x.GetType());
Which will output System.String. How could I get the compile time type System.Object here?
I took a look over at System.Reflection, but got lost in the amount of possibilities it provides.
I don't know if there is a built in way to do it but the following generic method would do the trick:
void Main()
{
object x = "this is actually a string";
Console.WriteLine(GetCompileTimeType(x));
}
public Type GetCompileTimeType<T>(T inputObject)
{
return typeof(T);
}
This method will return the type System.Object since generic types are all worked out at compile time.
Just to add I'm assuming that you are aware that typeof(object) would give you the compile time type of object if you needed it to just be hardcoded at compile time. typeof will not allow you to pass in a variable to get its type though.
This method can also be implemented as an extension method in order to be used similarly to the object.GetType method:
public static class MiscExtensions
{
public static Type GetCompileTimeType<T>(this T dummy)
{ return typeof(T); }
}
void Main()
{
object x = "this is actually a string";
Console.WriteLine(x.GetType()); //System.String
Console.WriteLine(x.GetCompileTimeType()); //System.Object
}
When I run the following:
ParentClass foo = serializer.Deserialize(xmlReader) as ParentClass;
The xml document loaded in xmlReader is an inherited type of ParentClass. When examined in the debugger, foo is showing as being an instance of the inherited class, not the parent class. Of course, the inherited class is also of type ParentClass, but why does the as keyword have this behavior? Why doesn't C# strip out all the other object information not required to convert to ParentClass.
This is not a problem, but more or less a question out of curiosity.
The object itself is not modified, which is why the object's type is still displayed as "ParentClass" in the debugger.
Consider the following example, which I think is illustrative. What do you think is output to the console here?
class Program
{
public class ParentClass
{
public virtual void foo()
{
Console.WriteLine("parent.foo");
}
public virtual void bar()
{
Console.WriteLine("parent.bar");
}
}
public class InheritedClass : ParentClass
{
public new void foo()
{
Console.WriteLine("inherited.foo");
}
public override void bar()
{
Console.WriteLine("inherited.bar");
}
}
static void Main(string[] args)
{
var inherited = new InheritedClass();
var parent = inherited as ParentClass;
var d = parent as dynamic;
parent.foo();
inherited.foo();
d.foo();
parent.bar();
inherited.bar();
d.bar();
Console.Read();
}
}
Only one object is created, and then two more references to it are created: one with the inherited static type, and one with the "dynamic" type. That all references refer to the same object is demonstrated by the fact that invoking "bar" invokes "InheritedClass.bar" regardless of the static type (the runtime type is always the same).
However, notice the difference between using "override" and "new": you will see that "parent.foo()" invokes the "ParentClass.foo" method. That is because the "parent" variable is of the static type "ParentClass" type, and so the C# compiler emits IL instructions to call the method on "ParentClass". You can see further that the "dynamic" type reference still calls "InheritedClass.foo", because dynamic types resolve at runtime, and this resolves to the actual runtime type which is "InheritedClass".
Edit #InBetween has an important distinction that I didn't consider. In the case of casting from a value type to a reference type (or vice versa), a new object is actually created, as new memory must be allocated on the heap or stack respectively (the "boxing" process). Of course, partly for this reason, virtual methods are not supported for struct and other value types.
as can only perform reference conversions, nullable conversions, and boxing conversions. It wont perform any other type of conversions like user-defined conversions.
In your case its performing a compatible reference conversion; the object remains the same, you are only changing the reference.
But as can "modify" an object in the sense that I think you are saying when, for example, boxing which entails more than simply converting the reference.
var o = 1 as object;
o is an alltogether different object than integer 1.
It is important to note though that in any succesful as conversion GetType() will still return the original type of the object which is not the general behavior of the cast operator.
If I am passing an object to a method, why should I use the ref keyword? Isn't this the default behaviour anyway?
For example:
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t.Something = "Bar";
}
}
public class TestRef
{
public string Something { get; set; }
}
The output is "Bar" which means that the object was passed as a reference.
Pass a ref if you want to change what the object is:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
After calling DoSomething, t does not refer to the original new TestRef, but refers to a completely different object.
This may be useful too if you want to change the value of an immutable object, e.g. a string. You cannot change the value of a string once it has been created. But by using a ref, you could create a function that changes the string for another one that has a different value.
It is not a good idea to use ref unless it is needed. Using ref gives the method freedom to change the argument for something else, callers of the method will need to be coded to ensure they handle this possibility.
Also, when the parameter type is an object, then object variables always act as references to the object. This means that when the ref keyword is used you've got a reference to a reference. This allows you to do things as described in the example given above. But, when the parameter type is a primitive value (e.g. int), then if this parameter is assigned to within the method, the value of the argument that was passed in will be changed after the method returns:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
You need to distinguish between "passing a reference by value", and "passing a parameter/argument by reference".
I've written a reasonably long article on the subject to avoid having to write carefully each time this comes up on newsgroups
In .NET when you pass any parameter to a method, a copy is created. In value types means that any modification you make to the value is at the method scope, and is lost when you exit the method.
When passing a Reference Type, a copy is also made, but it is a copy of a reference, i.e. now you have TWO references in memory to the same object. So, if you use the reference to modify the object, it gets modified. But if you modify the reference itself - we must remember it is a copy - then any changes are also lost upon exiting the method.
As people have said before, an assignment is a modification of the reference, thus is lost:
public void Method1(object obj) {
obj = new Object();
}
public void Method2(object obj) {
obj = _privateObject;
}
The methods above does not modifies the original object.
A little modification of your example
using System;
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t = new TestRef();
t.Something = "Bar";
}
}
public class TestRef
{
private string s;
public string Something
{
get {return s;}
set { s = value; }
}
}
Since TestRef is a class (which are reference objects), you can change the contents inside t without passing it as a ref. However, if you pass t as a ref, TestRef can change what the original t refers to. i.e. make it point to a different object.
With ref you can write:
static public void DoSomething(ref TestRef t)
{
t = new TestRef();
}
And t will be changed after the method has completed.
Think of variables (e.g. foo) of reference types (e.g. List<T>) as holding object identifiers of the form "Object #24601". Suppose the statement foo = new List<int> {1,5,7,9}; causes foo to hold "Object #24601" (a list with four items). Then calling foo.Length will ask Object #24601 for its length, and it will respond 4, so foo.Length will equal 4.
If foo is passed to a method without using ref, that method might make changes to Object #24601. As a consequence of such changes, foo.Length might no longer equal 4. The method itself, however, will be unable to change foo, which will continue to hold "Object #24601".
Passing foo as a ref parameter will allow the called method to make changes not just to Object #24601, but also to foo itself. The method might create a new Object #8675309 and store a reference to that in foo. If it does so, foo would no longer hold "Object #24601", but instead "Object #8675309".
In practice, reference-type variables don't hold strings of the form "Object #8675309"; they don't even hold anything that can be meaningfully converted into a number. Even though each reference-type variable will hold some bit pattern, there is no fixed relationship between the bit patterns stored in such variables and the objects they identify. There is no way code could extract information from an object or a reference to it, and later determine whether another reference identified the same object, unless the code either held or knew of a reference that identified the original object.
This is like passing a pointer to a pointer in C. In .NET this will allow you to change what the original T refers to, personally though I think if you are doing that in .NET you have probably got a design issue!
By using the ref keyword with reference types you are effectively passing a reference to the reference. In many ways it's the same as using the out keyword but with the minor difference that there's no guarantee that the method will actually assign anything to the ref'ed parameter.
ref mimics (or behaves) as a global area just for two scopes:
Caller
Callee.
If you're passing a value, however, things are different. You can force a value to be passed by reference. This allows you to pass an integer to a method, for example, and have the method modify the integer on your behalf.