The following code works fine:
public static void Main()
{
Foo<int>(5);
}
private static void Foo<T>(T x)
{
Bar((int)(object)x);
}
private static void Bar(int x)
{
}
However, my Bar method comes from a third-part library (Json.NET) that implements multiple overloads. Example:
private static void Bar(string x)
{
}
If I call Foo<int>(5), the Bar((int)(object)x) conversion works fine, but calling Foo<string>("") breaks at runtime (for obvious reasons, you can't convert string to int).
So, I would like to change the Bar((int)(object)x) conversion to a generic Bar((T)(object)x) conversion, but this gives the following compilation error:
cannot convert 'T' to 'int'
So, is it possible to convert object to T or the only solution is to using a switch-case convertion?
The error actually means that the compiler doesn't know which overload of Bar to invoke, since T could be any type at compile time.
You would need check if T is int or string at runtime and explicitly cast to the needed type.
if (typeof(T) == typeof(int))
Bar((int)(object)x);
else if (typeof(T) == typeof(string))
Bar((string)(object)x);
else
throw new Exception();
This generates an error saying I cannot convert type ClassType
to T. Is there any workaround for this?
Is there any way to specify that the type of this can in fact be converted to T?
public void WorkWith<T>(Action<T> method)
{
method.Invoke((T)this);
}
Two possible solutions:
Not type-safe:
public void WorkWith<T>(Action<T> method)
{
method.Invoke((T)(object)this);
}
This isn't typesafe because you can pass it any method that has a single parameter and no return value, like:
WorkWith((string x) => Console.WriteLine(x));
The typesafe "version" (using generic constraints):
public class MyClass
{
public void WorkWith<T>(Action<T> method) where T : MyClass
{
method.Invoke((T)this);
}
}
The point here is that to be able to cast this to T, the compiler wants to be sure that this is always castable to T (so the need for the constraint). As shown in the not-type-safe example, the "classical" (unsafe) solution used with generics is passing through a cast to object.
public void WorkWith<T>(Action<T> method) where T: ClassType {
method.Invoke((T)this);
}
public interface ILovable<T> where T : IEquatable<T>
{
T Care(T t);
}
public class Me : ILovable<int>
{
public int Care(int i)
{
return i;
}
}
Say I have the above. Now below function fails:
private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
{
var z = me.Care(1); //cannot convert from 'int' to 'T'
}
What's failing the above piece of code? ILovable<T> has a Care function which intakes a T which is IEquatable<T>. In the above function I'm calling the same Care function and passing T which is int type. int is after all IEquatable<int>.
What am I doing wrong? Is there any work around to get it fixed?
Your method signature does not specify a ILovable<int>, it specifies an ILovable<T>. This, for example, would work:
private static void Colour(ILovable<int> me)
{
var z = me.Care(1); //cannot convert from 'int' to 'T'
}
The problem is the compiler doesn't know that T is an 'int' in your example; it could be any type that meets the constraint. Here is another way that would work:
private static void Colour<T>(ILovable<T> me, T valueToCareAbout) where T : IEquatable<T>
{
var z = me.Care(valueToCareAbout);
}
//use like this
Colour(me, 1);
The error I get is:
Argument type 'int' is not assignable to parameter type 'T'
I'm pretty sure this is because you are defining me as an ILovable<T>. Therefore, it doesn't automatically resolve to the Me type where int is defined as T.
This will fix the error because Me defines T as an int:
private static void Colour<T>(Me me) where T : IEquatable<T>
{
var z = me.Care(1);
}
Well that's because method Colour says that there will be parameter of type ILovable< T > whereas T would be resolved later, so at compile time either I tell method that T is int type.
So either you pass ILovable as parameter and grantee that T is int
void Colour<T>(ILovable<int> me)
or pass type Me directly
void Colour<T>(Me me)
Because otherwise me.Care is expecting type T not int as specific
Change following
private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
To
private static void Colour<Int32>(ILovable<int> me)
and above will work.
Now the mystry portion
You are getting error in following
private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
because Care is expecting T, and you are providing int.
It is same as
Care((T)1).
or
T t = (T)1; //This is the cause of error as int cannot be changed to T. Remember Int32 is sealed so T cannot derive from int
Care(t); // This is fine
To make above work, T has to int. To make it so, Colur method syntax should be like
private static void Colour<Int32>(ILovable<int> me)
If you want to pass string to Care, T should be string.
private static void Colour<string>(ILovable<string> me)
{
me.Care("Hello");
}
Now if we have to fix T then question arises why T is required at all in Colour definition.
Answer -> For non taking care of inheritance type in non sealed class.
The short answer is overriding variable of type T inside a generic method (or class) with a more derived type is not possible since compiler doesn't explicitly know T is that more derived type (in our case T is int), because T can be any other more derived type at run time.
Long answer: me variable is of type ILovable<T>. Now me.Care function is expecting parameter of type that is specified on ILovable<T> which is T. Outside the Care function T can be anything that is IEquatable<T>, so int is ok. But inside the function, T has to be just T and not another derived type of IEquatable<T>. Otherwise there will be runtime error for scenarios like this:
private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
{
var z = me.Care(1);
}
...
Colour("");
Right now, T is string when calling Colour(""). So me is ILovable<string>. So me.Care function expects a string as parameter but provided is an int and that is disaster.
I'm not sure how to phrase this question concisely without just giving the example so here goes:
public interface IThing<T>
{
void Do(T obj);
}
public class ThingOne : IThing<int>
{
public void Do(int obj)
{
}
}
public class ThingTwo : IThing<string>
{
public void Do(string obj)
{
}
}
public class ThingFactory
{
public IThing<T> Create<T>(string param)
{
if (param.Equals("one"))
return (IThing<T>)new ThingOne();
if (param.Equals("two"))
return (IThing<T>)new ThingTwo();
}
}
class Program
{
static void Main(string[] args)
{
var f = new ThingFactory();
// any way we can get the compiler to infer IThing<int> ?
var thing = f.Create("one");
}
}
The question appears to be here:
// any way we can get the compiler to infer IThing<int> ?
var thing = f.Create("one");
No. You would need to explicitly specify the type:
var thing = f.Create<int>("one");
You can't infer the return type without having a parameter used specifically in the method. The compiler uses the parameters passed to the method to infer the type T, and in this case, it's a single string parameter, with no parameters of type T. As such, there's no way to have this inferred for you.
No, you can't do this because the result of your Create factory method will be evaluated at runtime based on the value of the parameter. Generics are for compile-time safety and in your case you cannot have such safety because the parameter value will be known only at runtime.
My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}