Generics open and closed constructed types - c#

Recently I noticed that generic constructed types can be open and closed. But I do not understand what they actually mean. Can you give a simple example?

In practice the terminology doesn't really matter much - I can't remember the last time I had to worry about it except when trying to write about it.
An unbound type has no type arguments specified
A constructed type has at least one type argument specified
A type parameter is an open type
An array type where the element type is open is an open type
An open constructed type has at least one type argument which is an open type
A closed type is any type which isn't open
(There are further rules for nested types. Consult the C# 3.0 spec section 4.4 for gory details.)
As an example of an open constructed type, consider:
public class NameDictionary<T> : Dictionary<string, T>
The base class of typeof(NameDictionary<>) is:
Constructed because it specifies type arguments
Open because the second type argument (T) is an open type
The MSDN docs for Type.IsGenericType have quite a useful little table.
Just to reiterate, this is almost entirely unimportant in day to day use.
I'm generally in favour of knowing the correct terminology - particularly for things like "pass by reference" etc - but in this case it really, really doesn't come up very often. I would like to actively discourage you from worrying about it :)

From MSDN:
A generic type or method is closed if instantiable types have been substituted for all its type parameters, including all the type parameters of all enclosing types. You can only create an instance of a generic type if it is closed.
So this works as List<int> is closed:
var list = Activator.CreateInstance(typeof(List<int>));
But this throws an exception at run-time because List<> is open:
var list = Activator.CreateInstance(typeof(List<>));
↑

I have mostly used open generics (basically uninstantiated generics) in dependency injection mappings. For example, something like
Bind<IRepository<>>()
.To<BasicRepository<>>()
Then, when my object constructor contains:
public SomethingController(IRepository<Something>) { ... }
My dependency injection mechanism will instantiate a BasicRepository< Something > automagically. (This works with Ninject and StructureMap, and probably the Castle Windsor library; I'm not sure about other frameworks).

Related

What does it mean to put <> in code?

I am new to .NET C# and I was reading the code below:
var model = new TenantPageViewData<Tenant>(contentModel)
I can't understand <MyClass>, What does it mean to put <> in the code.
Also if you can guide me to documentation regarding this it will be great.
That is the syntax for specifying the type parameter for an open generic type. You can read more about generics here:
http://msdn.microsoft.com/en-us/library/512aeb7t.aspx
If you are new to C#, it will seem complicated at first, but a lot of the language makes use of this feature so it will be time very well spent learning it.
With the general documentation and answer out of the way, in this specific case, the TenantPageViewData exposes a generic parameter. You read that as "a TenantPageViewData<> of Tenant".
The signature for that class will look something like:
public class TenantPageViewData<T>
{
}
Where T is simply a placeholder you can reference in code that will, at compile-time, become strongly-typed to the type of argument you specify.
This class definition can be referred to as an "open" generic type because the placeholder T is, as yet, unrealised. The declaration var something = new TenantPageViewData<Tenant>() is a "closed" generic type because the generic argument is known to now be Tenant in this instance.
Type identity is per closed generic type, so a TenantPageViewData<Tenant> is not a TenantPageViewData<Landlord>, and static members of a generic class honour this also (which is a common pitfall of learning generics).
Other examples include List<string> usually read as "a List<> of string", and the comical Cup<T> :-)
these type of brackets I believe are used for marking generics.
http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
In C#, the angle brackets (< and >) are most often used to enclose a parameter of a generic class. For example, the .Net framework provides a List class where 'T' denotes the type of objects that will be contained in the list. Therefore, when the list is created as
List<string> myList = new List<string>();
you are creating a usable, type-safe instance of the List class.
Some good info on it here.

Are Generic Generic type parameters in C# allowed in some form

I would like to create the following class snippet
class Lookup<TKey,TValue,TCollection>
where TCollection : ICollection<>
{
public TCollection<TKey> _KeyCollection;
public TCollection<TValue> _ValueCollection;
}
Is this pattern in general possible in C#? In the current form the compiler does not like it. You can't seem to constrain a type parameter to be a generic. However it looks like it a reasonable thing to want to do. Is there any trick to achieve it?
Note: This question is specifically about generics and type constraints. It is not looking for a work around for what you think I might be trying to do in my wider application.
You can't constrain a generic type parameter to be an open generic type, which seems to be how you're attempting to use it in the rest of the class.
You asked for a spec reference, and there's not one place that seems to spell it out in a nice, concise manner.
The best I can find is in section 4.5 (from C# 5.0 spec):
As a type, type parameters are purely a compile-time construct. At run-time, each type parameter is bound to a run-time type that was specified by supplying a type argument to the generic type declaration. Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (§4.4.2). The run-time execution of all statements and expressions involving type parameters uses the actual type that was supplied as the type argument for that parameter.
But in your attempt, TCollection won't match up with this text because it's asking for an non-closed type.
You can't have an open generic type as a constraint. You can, however, have a closed generic type:
class Lookup<TKey, TValue, TKeyCollection, TValueCollection>
where TKeyCollection : ICollection<TKey>
where TValueCollection : ICollection<TValue>
{
public TKeyCollection _KeyCollection;
public TValueCollection _ValueCollection;
}
It may not be pretty and there are a lot of type parameters, but it is possible.

Confused in Type.GetType

I was reading C# in depth and I couldn't understand the para of the chapter
Another method—this time one that already existed in .NET 1.1—that’s
worth exploring is Type.GetType(string), and its related
Assembly.GetType(string) method, both of which provide a dynamic
equivalent to typeof. You might expect to be able to feed each line of
the output of listing 3.11 to the GetType method called on an
appropriate assembly, but unfortunately life isn’t quite that
straightforward. It’s fine for closed constructed types—the type
arguments just go in square brackets. For generic type definitions,
though, you need to remove the square brackets entirely— otherwise
GetType thinks you mean an array type. Listing 3.12 shows all of these
methods in action.
and in the example code author did what he asked not to do I believe :
string listTypeName = "System.Collections.Generic.List`1";
Type defByName = Type.GetType(listTypeName);
Type closedByName = Type.GetType(listTypeName + "[System.String]"); // did here ? , since he passed the listTypeName + [Type args] , so compiler should think it's array?
Type closedByMethod = defByName.MakeGenericType(typeof(string));
or might I got the things wrong , can anyone please elaborate with examples what he meant by line "For generic type definitions, though, you need to remove the square brackets entirely— otherwise GetType thinks you mean an array type"
System.Collections.Generic.List`1[System.String] is the name of the closed generic type.
And the name of the open generic type is not System.Collections.Generic.List`1[] but System.Collections.Generic.List`1.
That's basically all that this paragraph says.
.Net type names passed by string use [<type1>(,<typeN>)] to indicate a generic type/function parameter list. [] on it's own indicates an array type.
Also, any generic type name will have the construct:
`n
After its string name to indicate the number of generic parameters that the type has. So:
MyNamespace.MyType`1
References the open generic type MyNamespace.MyType<> (i.e. with no generic arguments supplied).
Whereas
MyNamespace.MyType`1[System.String]
References the closed generic type MyNamespace.MyType<string>.
Note that there are further rules to do with Type.GetType - that being that you can only omit the assembly name (including public key token if applicable) when either:
The type requested can be found in the calling assembly
The type request is in mscorlib.
So, many core types can be specified by string with just their namespace-qualified name, including the generics - and the same goes for when a type name is specified as a type argument (as with System.String above).

Instantiation with C# "dynamic" Keyword

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 .

Generics in C#, using type of a variable as parameter [duplicate]

This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 8 years ago.
I have a generic method
bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
How do I use the method in the following way:
Type t = entity.GetType();
DoesEntityExist<t>(entityGuid, transaction);
I keep receiving the foollowing compile error:
The type or namespace name 't' could
not be found (are you missing a using
directive or an assembly reference?)
DoesEntityExist<MyType>(entityGuid, transaction);
works perfectly but I do not want to use an if directive to call the method with a separate type name every time.
The point about generics is to give compile-time type safety - which means that types need to be known at compile-time.
You can call generic methods with types only known at execution time, but you have to use reflection:
// For non-public methods, you'll need to specify binding flags too
MethodInfo method = GetType().GetMethod("DoesEntityExist")
.MakeGenericMethod(new Type[] { t });
method.Invoke(this, new object[] { entityGuid, transaction });
Ick.
Can you make your calling method generic instead, and pass in your type parameter as the type argument, pushing the decision one level higher up the stack?
If you could give us more information about what you're doing, that would help. Sometimes you may need to use reflection as above, but if you pick the right point to do it, you can make sure you only need to do it once, and let everything below that point use the type parameter in a normal way.
One way to get around this is to use implicit casting:
bool DoesEntityExist<T>(T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
calling it like so:
DoesEntityExist(entity, entityGuid, transaction);
Going a step further, you can turn it into an extension method (it will need to be declared in a static class):
static bool DoesEntityExist<T>(this T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
calling as so:
entity.DoesEntityExist(entityGuid, transaction);
I'm not sure whether I understand your question correctly, but you can write your code in this way:
bool DoesEntityExist<T>(T instance, ....)
You can call the method in following fashion:
DoesEntityExist(myTypeInstance, ...)
This way you don't need to explicitly write the type, the framework will overtake the type automatically from the instance.
You can't use it in the way you describe. The point about generic types, is that although you may not know them at "coding time", the compiler needs to be able to resolve them at compile time. Why? Because under the hood, the compiler will go away and create a new type (sometimes called a closed generic type) for each different usage of the "open" generic type.
In other words, after compilation,
DoesEntityExist<int>
is a different type to
DoesEntityExist<string>
This is how the compiler is able to enfore compile-time type safety.
For the scenario you describe, you should pass the type as an argument that can be examined at run time.
The other option, as mentioned in other answers, is that of using reflection to create the closed type from the open type, although this is probably recommended in anything other than extreme niche scenarios I'd say.

Categories

Resources