In this topic one can find solution to make generic class which provides parsing from string to generic parameter type. However, it could happen that type given to this parameter does not provide such conversion. Is there a way to make constraint assuring that?
UPDATE:
Thank you for your answers. However I know I can generally make constraints. The problem is: is there any interface that all types, which Convert.ChangeType won't fail at, implements. Or which is implemented by all types with Parse(string) method.
Since, as I said in my comment, you can't add interfaces to specific types nor can you use duck-typing in generic type constraints, you'll probably have to end up writing a bit of a hacky solution. I think your best bet is to make several overloads of your parsing function, one for each of the basic types (int, char, string, etc.) and then provide a generic one that has IConvertible as its generic constraint. The compiler will choose the right overload, or none at all in the case of non-convertible types.
You need to use Type Constraints to restrict what types of objects can be used in the generic class. You should define an interface that can be used to do that conversion and than set that interface as the constraint.
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++)
I have read some content on variance, and want to make sure I fully get it. My understanding is that covariant is implicit conversion of the more-derived type to less and contravariance is the opposite. I further believe that covariance corresponds to the out keyword of the generic type definition. For example IEnumerable interface definition uses out to export the result of an argument, while IComperable's interface definition uses the in keyword to receive a value. I have not seen a generic type which does both, and don't see why it may not be possible. What am I missing?
I also read about the array[] support of variance and how there is a runtime check to make sure the types are the same.
The paper Valued Conversions by Kevlin Henney gives a motivation for a so-called variant value type functionality, as well as an outline of a C++ implementation. It is a good read and it covers exactly what I would like to have available in C#: a general type that can hold values of different value-types.
I have not been able to find anything like this in C# though. Somewhat similar questions on SO have unsatisfactory answers and comments like "this is probably not what you want". This surprises me because it looks like fairly commonly required functionality. Henney's C++ boost::any class is widely used.
Is it not possible to create this functionality in C#?
Edit: Responding to one of the answers, I do not think that generics will do the trick. Using a generic requires the developer to know what kind of value-type the Variant variable is holding, and that type becomes immutable for that particular Variant variable as well. But the Variant type I am talking about should be able to hold different types. For example, a function Variant ReadValue() could read an entry from a file, parse it, fill the Variant value accordingly and then return it. The caller does not know in advance what kind of type will be contained in the returned Variant.
This is what generics are for. List<T> where T is anything at all. Generics provide both compile-time and runtime type safety.
You could create your own generic type to store any value you want. You could also cast anything to object and pass it around as such.
You can also use generic constraints to limit your type, such as wanting to only have T be a reference type:
public MyClass<T> where T : class
Or a value type:
public MyClass<T> where T : struct
See more here: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
You can look into using dynamic for this as well.
The dynamic type enables the operations in which it occurs to bypass compile-time type checking. Instead, these operations are resolved at run time.
Type dynamic behaves like type object in most circumstances. However, operations that contain expressions of type dynamic are not resolved or type checked by the compiler.
From what I understand, using any in C++ is same as using combination of object and ChangeType method in C# with exception of having nice syntax for autoconversion from and into the any type. And without limitation just for value types.
Henney's article is quite old (year 2000). In a live lesson (London DevWeek 2008) I remember him explaining low coupling and implementing towards abstractions (interfaces) for the OCP (Open-Closed Principle). He was quite fond of generics and more so generic interfaces. So conceptually it's most probably exactly what he has written about back then, albeit I must admit I didn't read the article. C# generics are even a bit more robust then C++ templates, you should look at Covariance and Contravariance in Generics.
On another note:
What you can't do with generics are variable arity templates, which have been available for C and C++.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I often see (in many mocking libraries for example) methods where a generic type argument is used in place of an argument of type System.Type. I am specifically talking about cases where generic type is only being used in typeof(T) operation (i.e. no instance of type T is being used anywhere within the method, and T is not being used for either return type or other arguments).
For example consider following method:
public string GetTypeName(System.Type type) { return type.FullName; }
this method is often accompanied with a generic version:
public string GetTypeName<T>() { return GetTypeName(typeof(T)); }
Questions
is it a bad practice or a good practice?
Is this a syntactic sugar or are there more to it?
I see this as misusing a language feature to abbreviate a call to a method that accepts an argument of type System.Type
Would you consider this a smell? Should this be avoided? or is this actually a good practice (to provide a generic method as a shortcut to avoid typing typeof()).
Here are some practical issues with using this pattern I can think of:
if an argument of non System.Type type is added - method might need to be rewritten (if order of arguments is semantically significant) to non generic version (otherwise some arguments will be generic type arguments, and some will be regular arguments).
it requires two methods (generic and non generic for cases where type is not known at compile time). Consequently adds unit tests which are mostly meaningless.
On the other hand this is a common practice (and majority is always right, right?) but more importantly ReSharper prefers that signature when I do Extract Method refactoring on a code that requires single argument of type System.Type known at compile time (and I learned to take their recommendations though not on faith, but seriously).
I think you need to consider documentation. How obvious is it what the methods do? If you have two methods (one with Type and one with a type argument), users need to look at both and choose. People who aren't looking at your code may not realize that the second one simply calls the first.
Where it definitely makes sense to use both is when the type argument is actually used when it can be and there is some kind of fallback for the Type version. For example:
object GetThingOfType(Type type) { ... }
T GetThingOfType<T>() { return (T)GetThingOfType(typeof(T)); }
Another thing to consider: A type argument must always be written explicitly. If it is likely that there will be more than one operation to perform with the same type object, it's not helpful to use type arguments. Consider something like this:
var t = typeof(string);
var name = GetTypeName(t);
var assemblyName = t.Assembly.FullName;
Even though I know the type is string, I should not write GetTypeName<string> here because I would be repeating myself. By giving me an option that I would most often be better off not choosing, you're adding a bit of unnecessary complexity.
A more obscure point is IDE support of XML documentation. You document the type argument like this:
<typeparam name="T">important information</typeparam>
Then if you type GetTypeName< in C#, Visual Studio will show "T: important information". But, for some reason, when you type GetTypeName(Of in Visual Basic, it will not (as of 2012).
You are right: consider the semantics of the method. Is it operating on instances of the type, or on the type itself?
If it is operating on instances, then it should be a generic method. If it is on the type, then make it an argument of type Type.
So in your example I would say
public string GetTypeName(System.Type type) { return type.FullName; }
Whereas
public static int Count<TSource>(this IEnumerable<TSource> source)
Is operating on the instance source of type IEnumerable<TSource>.
In general, I have seen generics abused more than well-used. Any generic method implementation that does a typeof(T) or worse still, uses any kind of reflection is not really generic in my opinion and is an abuse. After all, generic means it works the same regardless of the type argument, doesn't it?
So, in summary, I agree with you - it smells.
I don't use the string GetName<T>() { return typeof(T).Name; } pattern as it is a misuse (misuse is probably strong but I can't think of the right word) of the design pattern that is the reason for generics, namely: generic type parameters are there for the compiler and the JITter (see the answer to this question) so that they can generate the type specific storage, parameters, stack variables, etc etc.
Using it as a convenient method for passing a type argument at runtime to me smells. There are times when typeof(T) is necessary, but I've found them to be rare and usually needed only when doing complex things with generics, as opposed to simple type safety sorts of things. If I see it, I definately pause and ask myself why it's there.
As it was already said, it looks to me like a matter of personal preferences. From my experience, most of the methods accepting an argument of type Type can be syntactically "sweetened" using an accompanying extension method.
So, in case of your example, I would make the second method an extension. Using this approach, you get a solution for your second concern - no unnecessary unit tests are required. The first one, however, remains; but then, addition of arguments will require refactoring anyway, so it will provide an opportunity to change the consumers of the extension method so they use the modified version of the original one.
Of course, it's just a personal opinion.
A generic method has an advantage over a method with a parameter of type Type, because it can reffer to other generic things using the provided type. This is particularly useful in the following scenario:
public string GetTypeName<T>()
{
return Cache<T>.TypeName;
}
private static class Cache<T>
{
public static readonly TypeName = GetTypeName(typeof(T));
}
This cache is easy, there is no need to mess around with dictionaries and it is automatically thread-safe.
This being said, if the implementation is not using this possibility, than the difference between the two is just cosmetic.
Methods that deal with types usually do just that: Dealing with types.
IMO, Class.Method<SomeType>(); is much better than Class.Method(typeof(SomeType));
But that is a matter of opinion I guess.
Consider LINQ's .OfType<T>(), for example:
personlist.OfType<Employee>().Where(x => x.EmployeeStatus == "Active");
versus:
personlist.OfType(typeof(Employee)).Where(x => ((Employee)x).EmployeeStatus == "Active");
which one would you prefer?
.NET knows many ways to convert data types:
Convert-class;
Functions inside a type like (Try)Parse and ToString, etc.;
Implementation of interface IConvertable;
The TypeConverter;
The implicit and explicit conversion operator;
Am I missing another one?
So if am converting one datatype to another, I need to know both types and I need to know which conversion method to use. And this becomes pretty nasty if one of those two types (or both) is a generic type.
So my question is: I there is uniform (generic) way in .NET to convert one data type to another, which might use all the other limited methods?
A good, generic way to convert between types is with Convert.ChangeType. Here's an example of how you could use it to write a generic converting method:
public static TResult Convert<TResult>(IConvertible source)
{
return (TResult)System.Convert.ChangeType(source, typeof(TResult));
}
It, like other Convert methods, internally calls the IConvertible interface.
This will not make use of your other conversion options:
The most common I'd think would be ToString; for that, you could add a check to see if TResult is string and if so, (after appropriate null checks) simply call ToString on your input.
Using reflection you could check for:
the TypeConverterAttribute (TypeDescriptor.GetConverter seems to be the way to go from there)
(Try)Parse methods, (which you'd invoke), and
implicit/explicit conversion operators (the methods op_Implicit and op_Explicit, which you'd likewise invoke)
These are each fairly self-explanatory if you know a bit about reflection, but I could elaborate if any prove difficult.
You imply those are all the same
They are not
Pick the appropriate
Convert Class
Converts a base data type to another base data type.
Parse is from string
ToString is a to string
IConvertible Interface
Defines methods that convert the value of the implementing reference
or value type to a common language runtime type that has an equivalent
value.
TypeConverter Class
Provides a unified way of converting types of values to other types,
as well as for accessing standard values and subproperties.
Yes you need to know the type you are converting to.
And you should be aware if the type you are converting from.
With generics there is no built in.
At best you provide a method.
But why do you need to convert generics?
You seem to imply that more than one way is a bad thing.
For a single way then I like the answer from Tim S. +1
But that does not mean I would ever use it.
The are even more ways to get data from a SQL database.
Is that a bad thing?