Suppose I've a generic method as:
void Fun<T>(FunArg arg) {}
Are this.Fun<Feature> and this.Fun<Category> different instantiations of the generic method?
In general, how does the generic method get instantiated? Different generic argument produces different method, or same method along with different metadata which is used at runtime?
Please support your answer with some quote(s) from the language specification.
Also, suppose I did these:
client.SomeEvent += this.Fun<Feature>; //line1
client.SomeEvent += this.Fun<Category>; //line2
client.SomeEvent += this.Fun<Result>; //line3
then later on,
client.SomeEvent -= this.Fun<Feature>; //lineX
Does the lineX undo the thing which I did at line1? Or it depends on somethig else also?
They all share a method definition, but at runtime they are different MethodInfo - because the generic type arguments define a generic method.
Supporting illustration:
Action<FunArg> a1 = Fun<X>;
Action<FunArg> a2 = Fun<Y>;
Action<FunArg> a3 = Fun<Y>;
Console.WriteLine(a1.Method == a2.Method); // false
Console.WriteLine(a3.Method == a2.Method); // true
At the JIT level, it is more complex; any reference-type parameters will share an implementation, as a reference is a reference is a reference (noting that all such T must satisfy any constraints in advance). If there are value-type T, then every combination of generic type arguments gets a separate implementation at runtime, since each requires a different final implementation.
It depends on the types involved.
For all the reference types (ie. classes), one method will be JITted to handle them all.
For all the value types (ie. structs), one method per type will be JITted.
So the information in the question is not detailed enough to answer, if Feature and Category are reference types, then yes, one method will be JITted for them. If one of them, or both, are value types, one method per value type will be JITted.
Note my use of the word JITted here. In the assembly compiled, there will be only one method, but at runtime, the JITter will create actual implementations of the generic methods according to the above rules.
Pop Quiz: What happens if you use NGEN on an assembly with generic types/methods? (hint: not what you think)
Yes, they will become two separate methods.
Related
As far as I understand, at runtime the CLR implementation creates different machine code (or whatever runtime representation) for the same generic Type with different parameterized valuetypes, but shares the machine code for reference types. This makes sense since reference types are going to take up the same size (the size of a reference).
What I don't understand is how this can work with code that explicitly uses code which depends on the type of T directly through something like typeof(T) or is T. For example, in the class:
class TestClass<T>
{
public static bool TestAType(Object pObj) { return pObj is T; }
}
I don't see how the same implementation for T = List and T = String can allow TestClass<String>.TestAType("hello") to be true and TestClass<List<int>>.TestAType("hello") to be false.
I'm making the assumption here that the machine code is the same for the compiled generic types, which could of course be false.
The native code generated for each generic instantiation using reference types is indeed the same (having System.__Canon as the parameter internally) but that doesn't mean the code should have no access to the original type arguments. The native code can access the metadata via helper functions and retrieve the types.
It would be useful to examine actual native code generated by such a method, but from browsing the SSCLI, it looks like this function does the job, according to its description:
// Given information about how to do a runtime lookup, generate the tree
// for the runtime lookup.
//
// Run-time lookup is required if the enclosing method is shared between instantiations
// and the token refers to formal type parameters whose instantiation is not known
// at compile-time.
I've read that reference types all use the same constructed class:
Generics work somewhat differently for reference types. The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with object references substituted for the parameters in the MSIL. Then, every time that a constructed type is instantiated with a reference type as its parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the generic type. This is possible because all references are the same size. (Generics in the Run Time (C# Programming Guide))
However when calling GetType() on constructed objects based on the same generic with different type parameters, two different types are recieved. Where A and B are both classes, and RefType is a generic:
RefType<A> a = new RefType<A>();
RefType<B> b = new RefType<B>();
Console.WriteLine("a type is "+a.GetType());
Console.WriteLine("b type is "+b.GetType());
results in:
"a type is RefType`1[A]"
"b type is RefType`1[B]"
Does this mean that the CLR handles the creation of Type objects for different constructed types even when there is no "real" specialized instantiation?
Is there a way to see directly what is and isn't generated by the CLR?
Does this mean that the CLR handles the creation of Type objects for different constructed types even when there is no "real" specialized instantiation?
Yes. Consider that run-time type checks are an important part of the language.
var x = new List<string>() as List<object>;
This is supposed to initialise x to null. If the run-time type information for new List<string>() had somehow lost the generic type parameter, this couldn't work.
Is there a way to see directly what is and isn't generated by the CLR?
class G<T> { public void f() { } }
class A { }
class B { }
struct C { }
struct D { }
enum E : int { }
static void Main(string[] args)
{
Console.WriteLine(typeof(G<object>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<string>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<A>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<B>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<C>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<D>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<E>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<int>).GetMethod("f").MethodHandle.Value);
}
You will see that G<object>.f, G<string>.f, G<A>.f and G<B>.f have the same method handle, but G<C>.f, G<D>.f, G<E>.f and G<int>.f all have different ones. Not even G<E>.f and G<int>.f share the implementation.
The Type objects give a type information at a high level of abstraction and tell you what the type is logically, whereas the implementation of generics is a low-level detail, that you should not rely on. Implementation details can always change.
T<A> and T<B> are two different types and therefore they must be described by to different Type objects. This is because a Type object not only yields information for T<>, but also for A or B, i.e. for the generic type parameters. The fact that the 2 types share the same code base makes no difference.
Type objects belong to the API. You can use this information in your code. The Type class might be extended in future to reflect new features of the language, but this is not a breaking change.
It is good to know the implementation details when you want to write efficient code. Some low-level tools (O/R-mappers, code weavers etc.); however, do sometimes depend on implementation details.
I've seen many examples of this tool which abstracts away the cumbersome syntax of Reflection. However none demonstrate instantiation of an unknown type. Is it safe to assume this isn't possible with "dynamic"?
Logically, it's impossible to instantiate an unknown type -- to instantiate a type, something must know what it is.
dynamic is useful for manipulating values of an unknown type (by assuming that it is capable of certain operations, which will fail at runtime if they are in fact not possible). To instantiate any type, however, you either need to use compile-time instantiation (e.g. using a C# constructor call), or else you need an instance of Type that corresponds to your desired type.
The compiler can use the dynamic keyword so that the dlr will construct a type, but it's designed to late bind the arguments of a constructor rather than the type to be constructed. The opensource framework ImpromptuInterface abstracts the dlr calls, including the constructor. If you need to call a constructor that has arguments this will run about 5 times faster than using reflection/Activator.
var x = Impromptu.InvokeConstructor(Type.GetType("SomeType"),args...);
I don't know what your goal is... but do you mean something like
dynamic X = Type.GetType("SomeUnknownType").GetConstructor(null).Invoke(null);
?
the above just calls the default (parameterless) constructor of the Type "SomeUnknownType" and assign the resulting instance to a dynamic .
Just out of curiosity:
Many LINQ extension methods exist as both generic and non-generic variants, for example Any and Any<>, Where and Where<> etc. Writing my queries I usually use the non-generic variants and it works fine.
What would be the cases when one has to use generic methods?
--- edit ---
P.S.: I am aware of the fact that internally only generic methods are called and the compiler tries to resolve the content of the generic brackets <> during compilation.
My question is rather what are the cases then one has to provide the type explicitly and not to rely on the compiler's intuition?
Always. The C# compiler is smart enough to infer what the type of the method is based on the parameters. This is important when the type is anonymous, and thus has no name.
obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);
obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
Edit: To be clear, you are always calling the generic method. It just looks like a non-generic method, since the compiler and Intellisense are smart.
Edit: To your updated question, you would want to be specific if you want to use a type that is not the type of the object you are passing. There are two such cases:
If the parameter implements an interface, and you want to operate on that interface, not the concrete type, then you should specify the interface:
obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
If the parameter is implicitly convertible to another type, and you want to use the second type, then you should specify it:
obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
On the other hand, if you need a cast to do the conversion (or you insert one anyway), then you don't need to specify:
obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
One example I ran into today:
ObjectSet<User> users = context.Users;
var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));
The above code won't work because the .Where method doesn't return an ObjectSet<User>. You could get around this one of two ways. I could call .AsQueryable() on users, to make sure it's strongly typed as an IQueryable, or I could pass specific type arguments into the Aggregate method:
criteria.Aggregate<Func<User, bool>, IEnumerable<User>>(
PersonSet, (u, c) => u.Where(c));
Another couple of more common examples are the Cast and OfType methods, which have no way to infer what type you want, and in many cases are being called on a non-generic collection in the first place.
In general, the folks that designed the LINQ methods went out of their way to avoid the need to use explicit types in these generic methods, and for the most part you don't need to. I'd say it's best to know it's an option, but avoid doing it unless you find it necessary.
What is the design decision to lean towards not returning an anonymous types from a method?
You can return an instance of an anonymous type from a method - but because you can't name it, you can't declare exactly what the method will return, so you'd have to declare that it returns just object. That means the caller won't have statically typed access to the properties etc - although they could still pass the instance around, access it via reflection (or dynamic typing in C# 4).
Personally I would quite like a future version of C# to allow you to write a very brief class declaration which generates the same code (immutable properties, constructor, Equals/GetHashcode/ToString) with a name...
There is one grotty hack to go round it, called casting by example. I wouldn't recommend it though.
Because an anonymous type has no name. Therefore you cannot declare a return type for a method.
Because C# is statically typed language and in a statically typed language the return type of a method needs to be known at compile time and anonymous types have no names.
How can you use your type inside your method if the definition is only in the call of the method ?
It's not javascript.
A lot of answers heere seem to indicatie that it is not possible because of the current syntax and rule. But the question is about changing them. I think it would be possible, but a little complicated and resulting in an awkward (error-prone) syntax. Like
var f() { return new { A = "*", B = 1 }; }
var x = f();
The question is whether this adds sufficient value to the language to make it worth it.
At least up to 3.5, anonymous types are actually resolved at compile time, and this would be impossible (or quite hard) to do with anonymous method signatures.