here's the code,
Type tbn = Type.GetType(dii.DictionaryName);
DictionaryXmlInfo4BaseDictionary<tbn>.AddDictionaryXmlInfo((message));//error
You can't use generics like that. Generics are meant to be used for types known at compile time.
You can do it with reflection - getting the generic DictionaryXmlInfo4BaseDictionary type definition, creating the closed type using Type.MakeGenericType, then calling AddDictionaryXmlInfo on it again by reflection... but it's relatively painful.
You cannot use generics with a type that is known only at runtime. The DictionaryXmlInfo4BaseDictionary<T> type is generic and requires the T argument to be known at compile time if you want to use it.
You can't use an instance of a type as a generic parameter.
The generic parameter should be the whatever the base instance is, DictionaryXmlInfo4BaseDictionary<object> in the most generic case, but you probably want something further down the class hierarchy than that.
You can't use Type in that way, refactor DictionaryXmlInfo4BaseDictionary so it takes a Type paramater as part of the method e.g.
DictionaryXmlInfo4BaseDictionary.AddDictionaryXmlInfo(tbn, message);
Related
The question "What is reification?" has a comment on C#'s generics:
Type information is maintained, which allows specialization to an extent, by examining type arguments using reflection. However, the degree of specialization is limited, as a result of the fact that a generic type definition is compiled before any reification happens (this is done by compiling the definition against the constraints on the type parameters - thus, the compiler has to be able "understand" the definition even in the absence of specific type arguments).
What does it mean by "specialization"? Is it not the same as instantiation of a generic type with a specific type argument?
What does it mean by "the degree of specialization is limited"?
Why is it "a result of the fact that a generic type definition is compiled before any reification happens"?
What does it mean by "specialization"? Is it not the same as instantiation of a generic type with a specific type argument?
Author explains in the portion of his answer dedicated to Java generics that
specialization of a generic type [is] the ability to use specialized source code for any particular generic argument combination.
In other words, it is an ability to do something special if a generic type parameter is of a specific type. Supplying an implementation of List<T> that represents individual elements as bits when you instantiate the type as List<bool> would be an example of specialization.
What does it mean by "the degree of specialization is limited"?
Author means that although you can write things like
if (typeof(T) == typeof(bool)) {
...
}
your abilities to respond to a combination of type arguments are limited, because any decision on a type combination has to be made at run-time.
Why is it "a result of the fact that a generic type definition is compiled before any reification happens"?
Because reification is done in CLR, well after C# compiler is out of the picture. The compiler must produce a generic type definition for CLR to use as a "template" for making closed constructed types for instances of a generic class.
I believe the meaning is as follows:
When you define a generic type e.g. MyGenericType<T> your definition has to make sense for any value of T, as the generic type is compiled before you actually use it in a specific implementation ("the degree of specialization is limited, as a result of the fact that a generic type definition is compiled before any reification happens").
Later on, when you actually use a MyGenericType<int> the compiler/jit will create a new class which is pretty much MyGenericType<T> with every mention of T replaced with int. This is the process of reification. This means that at runtime, you can use the fact that the generic type is using an int, but your ability to make use of this (specialisation) is limited, since when you defined MyGenericType<T> you didn't know this.
Specialization is used as antonym to generalization. When you created a generic type, you generalized a type definition. When you initialized it with a type, you specialized the compiled generic type to be able to create object of the type at run-time.
IL compiles the generic type. At runtime, this compiled generic type is combined with specific type argument to produce an object of the specified class.
Yes, specialization is same as instantiation of a generic type with a specific type argument at runtime.
With generics, come constraints which basically fix the scope of generic type. You can tell that by defining that T can be a struct, class, or has to have some specific base class etc. You cannot create a class instance which is not allowed by the constraints defined on the generic type.
You can initialize the same generic type definition with a int, string or another class, if it satisfied the constraints in the generic class.
It cannot directly create an object of the class with T, not yet replaced by a defined type (primitive types like int, string, or your custom class or interface) and your code inside should be compatible to type being passed in as T for it to work.
Refer (Links from same question you mentioned above):
NET Generics and Code Bloat
Generics are not templates (as in C++)
When I wanted a generic object extended from a class, in Java I used to write:
Class<AuthenticationProvider> c1;
What am I supposed to write in C# to do the same? How can I cast a Type Class Object in this format (a generic class extended from Authentication provider)?
Do you mean Type.MakeGenericType?
Edit:
Oops, I see what you mean now. No, you can't do this in C#, because System.Type is not a generic type! It contains information about a type, but there's nothing generic about it, so typeof(Foo) does not give you Type<Foo>.
I don't see why you'd need it either, though.
I have that code:
myDataGrid is an object passed to the method. I know it is type of OvserveableCollection of different types.
All I need is to cast that object to OvserveableCollection<T> (it implements the IEnumerable interface)
//get element's type
Type entryType = (myDataGrid as IEnumerable).AsQueryable().ElementType;
foreach (var item in (IEnumerable<entryType>)myDataGrid)
{}
but the compiler doesn't know the entryType in the loop header. Why ?
You can't use a runtime Type instance as a generic type parameter unless you use reflection (MakeGenericMethod() / MakeGenericType()). However I doubt it would help anyway! In this scenario, either use the non-generic IEnumerable (no <T>) API, or perhaps cast to a known interface/subclass, or use dynamic as a last resort duck-typing.
You can also use MakeGenericMethod() etc, but that is more involved and almost certainly slower.
For example:
foreach(object item in (IEnumerable)myDataGrid)
{
// tada!
}
Another trick can be to use dynamic to invoke the generic code:
public void Iterate<T>(IEnumerable<T> data)
{
foreach(T item in data) {...}
}
...
dynamic evil = myDataGrid;
Iterate(evil);
You're trying to use a Type variable as a type argument for a generic type. Generics don't work that way - you have to use a compile-time type as the type argument. (That compile-time type can be a type parameter itself, if you're doing this in a generic method.)
It's hard to know how to advise you to change the code without knowing more about your requirements though - what do you need to do with the items?
You can't cast to a "runtime type"... in order to "write" the instructions which actually implement that cast, the compiler requires the Type... which really just means that the Type must be known at COMPILE time.
The ONLY way I've ever found around this limitation was code-generator (of one sort or another) to "manually" generate the IL instructions to perform the cast. It's hard to know what to recommend unless we know a lot about your actual requirements (and constraints).
Cheers. Keith.
I was thinking about this. classes are obviously passed around by ptr. I suspect structs are passed around by copying it but i don't know for sure. (it seems like a waste for an int array to have every element a ptr. and passing ptrs for ints)
But thinking about it, List<MyStruct> can not know the size of my struct. What happens when i do this? Are there multiple copies of "List`1" and every time i use it with a storage size it does not have it creates a new implementation? (adjusting for the new offsets of T and such).
That could make sense since the source would be in the CIL inside of a DLL. But i am completely guessing, how is it done? Perhaps a reference or page # to the ECMA standards?
Generics use the concept of open and closed generic types: A parametrized generic class definition (i.e. List<T>) is an open generic type of which the runtime generates a closed generic type for each different use you have in your code, i.e. a different type is created for List<int> and for List<MyStruct> - for each closed generic type the size and type of T is known at run-time.
Clarification from MSDN:
When a generic type or method is
compiled into Microsoft intermediate
language (MSIL), it contains metadata
that identifies it as having type
parameters. How the MSIL for a generic
type is used differs based on whether
the supplied type parameter is a value
type or reference type.
When a generic type is first
constructed with a value type as a
parameter, the runtime creates a
specialized generic type with the
supplied parameter or parameters
substituted in the appropriate
locations in the MSIL. Specialized
generic types are created one time for
each unique value type that is used as
a parameter.
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.
The CLR compiles 1 version of the generic class and uses it for all reference types. It also compiles 1 version for every value type usage to optimize for performance.
Is there ever a reason to use Type parameters over generics, ie:
// this...
void Foo(Type T);
// ...over this.
void Foo<T>();
It seems to me that generics are far more useful in that they provide generic constraints and with C# 4.0, contravarience and covarience, as well as probably some other features I don't know about. It would seem to me that the generic form has all the pluses, and no negatives that the first doesn't also share. So, are there any cases where you'd use the first instead?
Absolutely: when you don't know the type until execution time. For example:
foreach (Type t in someAssembly.GetTypes())
{
Foo(t);
}
Doing that when Foo is generic is painful. It's doable but painful.
It also allows the parameter to be null, which can be helpful in some situations.
Well they really aren't the same at all.
With the second one, you've actually got a class of the compile-time type there (whatever has been passed in by whoever). So you can call specific functions on it (say if it's all of some given interface).
In your first example, you've got an object of class 'Type'. So you'll need to still determine what it is and do a cast to do anything useful with it.
Foo(someVariable.GetType()); // allowed
Foo<someVariable.GetType()>(); // illegal