Reputation: 85
How do I create a C# generic method that takes in one generic type and returns another generic type? How do i get the actual Type of T so that i can return my new type as that generic T type.
Basically, I want to achieve something like this sample code where the if
/else
logic converts between types. If there's a better way to do the same thing like with using Func please let me know. Any help would be appreciated. thank you.
EDIT: OK this is almost exactly what I want to do. (Just the types are different) I don't think "Convert.ChangeType" would work because I am using custom types.
public interface ICustomType{}
public struct TypeA : ICustomType {}
public struct TypeB : ICustomType {}
public struct TypeC : ICustomType {}
public static T Convert<T>(ICustomType input) where T : ICustomType
{
var output = default(T);
if (output is TypeA)
{
if (input is TypeA)
{
output = input;
}
else if (input is TypeB)
{
output = CustomTypeB_ToTypeA_Converter(input);
}
else if (input is TypeC)
{
output = CustomTypeC_ToTypeA_Converter(input);
}
}
else if (output is TypeB)
{
if (input is TypeA)
{
output = CustomTypeA_ToTypeB_Converter(input);
}
else if (input is TypeB)
{
output = input;
}
else if (input is TypeC)
{
output = CustomTypeC_ToTypeB_Converter(input);
}
}
else if (output is TypeC)
{
// same pattern as above
}
return output;
}
possible use case:
TypeA a = 45;
TypeB result = Convert<TypeB>(a);
Upvotes: 1
Views: 163
Reputation: 85
Ok after a break I came back and was able to solve my problem. It turns out all i had to do was pass my type back as the constraint interface and then cast it to the generic T before i return it. And that's it, everything worked. Thanks all for the help.
public interface ICustomType{}
public struct TypeA : ICustomType {}
public struct TypeB : ICustomType {}
public struct TypeC : ICustomType {}
public static T Convert<T>(ICustomType input) where T : ICustomType
{
var output = default(T);
if (output is TypeA)
{
if (input is TypeA)
{
output = (T)input;
}
else if (input is TypeB)
{
// first assign my type to ICustomType interface
ICustomType typeA = CustomTypeB_ToTypeA_Converter(input);
// then cast that interface to the generic T before you return it
output = (T)typeA;
}
else if (input is TypeC)
{
// first assign my type to ICustomType interface
ICustomType typeC = CustomTypeC_ToTypeA_Converter(input);
// then cast that interface to the generic T before you return it
output = (T)typeC;
}
}
else if (output is TypeB)
{
// same pattern as above
}
else if (output is TypeC)
{
// same pattern as above
}
return output;
}
Upvotes: 0
Reputation: 932
You can try this:
public static void Main()
{
var str = "1.0";
decimal result = Convert(str, ConvertToDecimal);
}
public static decimal ConvertToDecimal(string str)
{
return decimal.Parse(str);
}
public static TOut Convert<TIn, TOut>(TIn item, Func<TIn, TOut> f)
{
return f(item);
}
Upvotes: 1
Reputation: 169200
Well, if you don't know anything about the types the best thing you could do is basically to use the ChangeType method as suggested by Rob and Rabban:
public static class Program
{
public static void Main()
{
string s = "1";
double d = Convert<string, double>(s);
Console.WriteLine(d);
}
public static TOut Convert<TIn, TOut>(TIn text)
{
return (TOut)System.Convert.ChangeType(text, typeof(TOut));
}
}
Note that this will throw an exception at runtime if you try to use the method with incompatible values and types though:
public static void Main()
{
string s = "T";
//THIS WILL THROW A FORMATEXCEPTION
double d = Convert<string, double>(s);
Console.WriteLine(d);
}
So using generics like this is probably not the best way to solve whatever you are trying to do.
Upvotes: 0