I have two Enumerators and a method that takes an enumerator. They are called ABC and DEF and the method is called TestMethod(Enum myEnum). Code is below:
public enum ABC
{
Zero,
One,
Two
};
public enum DEF
{
Zero,
One,
Two
};
public void TestEnum(Enum myEnum)
{
...
}
The function TestEnum takes any enumerator. How can I test which one of the two does the passed in parameter belong to? I could blindly start testing it out with try / catch casting but sheesh that's ugly. Any cleaner ways of doing this? Thank you in advance for any help.
How can I test which one of the two does the passed in parameter belong to?
You can just call GetType:
Type type = myEnum.GetType();
It's not clear what you want to do with it after that, mind you.
Alternatively:
if (myEnum is ABC)
{
}
else if (myEnum is DEF)
{
}
EDIT: If you're able to change the method signature and if your callers will know the type, then as per Jeppe's comment, you could use:
public void TestEnum<T>(T value) where T : struct
{
// Use typeof(T) here
}
You can't constrain T to be an enum type with normal C#... although there are hacky ways of writing code with such constraints applied via post-processing.
Mr. Skeet already nailed this but!
What about two methods.
public void TestEnum(ABC abcEnum) {
//do ABC stuff
}
public void TestEnum(DEF defEnum) {
//do DEF stuff
}
You get the branching you need but without having to worry about getting the if statement right. True it's only an if statement but what if you add enum GHI. Now there's some unaccounted for input for TestEnum to handle. Using overloaded methods you'd catch that while compiling (or even better, intellisense would catch you).
Related
I am currently trying to get some casting on generic types done.
So the base idea is to have a method which accepts a generic Type and does different stuff depending on which type gets passed in.
For simplicity reasons I will just showcase the use of float, bool and default
The setup looks something like this (where T is a generic type defined by the class itself):
protected T DoStuff(T value)
{
switch (value) {
case float floatValue:
float result = DoFloatStuff(floatValue);
switch (result) {
case T output:
return output;
}
case bool boolValue:
bool result = DoBoolStuff(boolValue);
switch (result) {
case T output:
return output;
}
default:
// return value;
DoRealGenericStuff(value) // Edited, since I just want to sort out some special cases
}
}
Where DoFloatStuff and DoBoolStuff are just methods that have 1 parameter and a return type of their types respectively.
If I don't do it like that (I tried some typeof() casting before), the compiler always complains that it cannot cast from T to float and vice versa, even tho I made sure that would be the case with some Case-Switch / If-Else statements.
Does anybody know some better way to do this?
Thanks in advance,
BOTHLine
Edit:
Since a lot of people said kind of the same thing, that I either shouldn't use generics at all in a case like that or my methods would need to be more generic themselves..
My problem here is that I need to use 3rd party methods to handle the special cases I'm checking for (in this case the float and bool types). For the default case I already handled everything in a generic way. But for some defined types I just can't do that.
So to go a little more in detail why that's the case:
I'm currently working on a Plugin for the "Unity Engine". Unity has built in methods to display types (kind of all primitive types and some Unity-specific types). I have a generic Wrapper class which should be able to contain any types. But then when I want to display the content of that wrapper in the GUI that Unity Editor offers, I have to use the built-in methods to display the primitives (something like UnityEditor.EditrGUI.FloatField()). Without those methods I am never able to display anything.
Anything else which can be broken down to those types can then be displayed in a more generic way.
So the base idea is to have a method which accepts a generic Type and does different stuff depending on which type gets passed in.
That is the wrong idea. It's not the way generics should be used. In such a case, you should use method overloading to create the DoStuff for each type individually:
float DoStuff(float value) {/* float implementation here */}
bool DoStuff(bool value) {/* bool implementation here */}
...
The point of generic is to enable you to write a code that will run the same on different types - so it should either be used where the type itself is irrelevant to the code (like in any generic collection) or can be executed with an interface or a base class all the acceptable types implement (or inherits). At this point, generics is usually only needed when you want a method to return a specific implementation of an interface (or base class).
Let the compiler sort it out for you:
protected void DoStuff(float v){}
protected void DoStuff(int v){}
// and so on
//and finally the default:
protected void DoStuff(object v){}
public void Work(T value)
{
DoStuff(value)
}
This is not the short answer but it's the right way (by many standards). There might be a short answer but, if I were you I wouldn't bother.
This is the smell of a factory pattern. A generic should be, as the name suggests, generic and indifferent to the types if it is you can do something like this.
interface IDoStuffer<T>
{
T DoStuff(T value)
}
class DoStuffFloat : IDoStuff<float>
{
public float DoStuff(float value)
{
//Do your float stuff
}
}
class DoStuffBool : IDoStuff<bool>
{
public bool DoStuff(bool value)
{
//Do your bool stuff
}
}
Then you can have a factory give you a correct implementation
class DoStuffFactory
{
public IDoStuff<T> GetDoStuff<T>()
{
if(typeof(T) == typeof(float))
return new DoStuffFloat();
//And other types
}
}
I have a function that takes in a bool, shown below:
public void LoadEndPoints(bool mock)
{
}
I can call this via LoadEndpoints(true) or LoadEndpoints(false), but this can be a bit hard to understand, as you need to know what true/false represents. Is there a way to pass the parameter name and value to a function such as LoadEndPoints(mock = true)?
Yes!
You can specify the parameter names like this:
myObject.LoadEndPoints(mock: true);
Further Reading
Named and Optional Arguments (C# Programming Guide)
Another way to improve readability of your code would be to use an enum, like this:
public enum LoadOption
{
Normal,
Mock
}
public void LoadEndPoints(LoadOption option)
{
...
}
Then the call would look a bit like this:
myObject.LoadEndPoints(LoadOption.Mock);
You could use 'Named arguments', a C# 4.0 feature; and thus call: myObject.LoadEndPoints(mock : true);
If readability is indeed your prime concern, you could even expose two explicit methods, and internally reuse the logic - something similar to:
public void LoadEndPointsWithoutMock()
{
LoadEndPoints(false);
}
public void LoadEndPointsByMocking()
{
LoadEndPoints(true);
}
private void LoadEndPoints(bool mock)
{
}
Also, I wouldn't say that LoadEndPointsWithoutMock, etc. are great method names. Ideally, the names should have something to do with the domain.
You can use a KeyValuePair:
KeyValuePair kvp = new KeyValuePair(BoolType, BoolValue)
Yes, you can do it with the following syntax in c#:
myObject.LoadEndPoints(mock : true);
And in VB:
myObject.LoadEndPoints(mock := true)
Use named parameters. Have a look at this Named and Optional Arguments
Is there a way to invoke a generic function with a type known only at run time?
I'm trying to do something like:
static void bar()
{
object b = 6;
string c = foo<typeof(b)>();
}
static string foo<T>()
{
return typeof (T).Name;
}
Basically I want to decide on the type parameter only at run time, but the function I'm calling depends on the type parameter.
Also I know this can be done with reflections... but it's not the nicest solution to the problem...
I'm sort of looking for dynamic features in C#...
I'm writhing a bridge between two classes the first one is basically a big tree with different types of of objects (composite by interface) the other is a sort of a "super visitor".
the supper visitor accepts key-value dictioneries that map types to object it looks like:
dic.Add(object value)
and T is not necessarily the type of the value... a lot of times it isn't...
I know it's written poorly, but i can't fix it...
I can work around it, but only at runtime...
I already did it with reflections, but if there's a better way to do it without them i would be happy to learn...
Thank you
This is a bit of a hack but you can get dynamic to do the reflection work for you by something like,
class Program
{
static void Main(string[] args)
{
var b = 6;
var t = (dynamic)new T();
var n = t.Foo(b);
}
class T
{
public string Foo<T>(T a)
{
return typeof(T).Name;
}
}
}
Here the dynamic call will extract the type of b and use it as a type parameter for Foo().
You can use dynamic keyword if you're using .NET 4. In a word, the type of the variable will be resolved at run time so it is a super generic type ;) You can read a article here or read the MSDN documentation
Saly refelction is THE solution to the problem, whether it is nice or not is irrelevant here. It is the runtime designed mechanism to achieve exactly this. As there is no parameter or generics to use as input, this is the only way to do it - it is also senseless. As in: your example is bad. Because in the example the type is hardcoded.
If the method where b exists has b as generic parameter, the type is available for passing to foo. If not - reflection is THE way to go, albeit the syntax looks clumsy. Only one time, though.
This I believe is the only way:
var foo = typeof(Foo<>).MakeGenericType(typeof (bar));
You can set up a class which takes a type parameter at run time which can be used in the methods in that class.
public class GenericClass<T>()
{
ICommonInterface TheObject;
public GenericClass(T theObject)
{
TheObject = theObject;
}
public string GetName()
{
return TheObject.Name;
}
}
But this is only really useful if the Types being passed in share interfaces so have common properties between them. In your example it seems that relection is the answer as depending on the type you want to access specific properties.
I wrote a Generic Class:
public class Interval<T> where T : IComparable // for checking that Start < End
{
public T Start { get; set; }
public T End { get; set; }
...
}
And I use this class with DateTime, int, etc.
I need a Duration property that returns a duration like:
public object Duration
{
get
{
return End - Start;
}
}
But when this property is included in my class, the compiler raises a logical error on the - operator.
What can I do to achieve this goal normally, or should I ignore it?
Try something like this:
static void Main(string[] args)
{
Tuple<int, bool> value = JustAMethod<int>(5, 3);
if (value.Item2)
{
Console.WriteLine(value.Item1);
}
else
{
Console.WriteLine("Can't substract.");
}
}
public static Tuple<T, bool> JustAMethod<T>(T arg1, T arg2)
{
dynamic dArg1 = (dynamic)arg1;
dynamic dArg2 = (dynamic)arg2;
dynamic ret;
try
{
ret = dArg1 - dArg2;
return new Tuple<T, bool>(ret, true);
}
catch
{
return new Tuple<T, bool>(default(T), false);
}
}
How this works: first, you convert the arguments to a dynamic type, and you can easily use operators on the dynamic type. If you wouldn't be able to use the operators, then an exception would be thrown at runtime. So, if you try to substract two objects that you actually can't substract, we'll catch the exception and return false as the second item in the Tuple.
This is not possible with generics in C# - at least not directly. It has been a highly requested feature on Connect for a long time.
You will need to make your types implement some interface that has a member that can be used, and constrain the class to that, or use one of the workarounds listed in the Connect bug (none of which are perfect), or a separate approach like MiscUtil's generic operators.
this work
public object Duration
{
get
{
return (dynamic)End - (dynamic)Start;
}
}
but no check, and slow
Check Jon Skeet's Misc Util https://jonskeet.uk/csharp/miscutil/
And here the generic operators by Marc Gravell: https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html
The compiler does this so you don't write buggy code, its the whole point of generics and the concept of type safe programming.
If you need a method that subtracts dates write one that accepts a date, and if you need another one for integers, guess what you should write one for integers. Generics are not there so that the compiler can assume responsibility for any type. Think about it what if I wanted the difference between two objects, how would I do that with your generic method?
Or as #Reed Copsey mentioned you can constrain a class to it.
While this may seem like a major restriction, you need to remember that generics are generic. Of course, the System.Int32 type can work just fine with the binary operators of C#. However, for the sake of argument, if <T> were a custom class or structure type, the compiler cannot assume it has overloaded the +, -, *, and / operators.
I have the following C# class:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value ;
Parser.TryParse(p_value, out value);
// Do something with value
}
}
The point is to call the right Parser.TryParse method, depending on the generic type T.
This uses the following static class:
static public class Parser
{
static public void TryParse(string p_intput, out object p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out double p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out int p_output)
{
// Do something and return the right value
}
}
I expected this to work: In the worst case, the "object" TryParse would be called. Instead, I have two compilation errors:
CS1502: The best overloaded method match for 'Parser.TryParse(string, out object)' has some invalid arguments
CS1503: Argument 2: cannot convert from 'out T' to 'out object'
Question 1: I don't understand why this doesn't work: I can be naive, but aren't all C# objects supposed to derive from "object" ? Why T cannot be converted to object?
Question 2: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T) ?
Note
The question was edited to reflect the original question intent (as written in the title: How to dispatch C# generic method call into specialized method calls)
Actually, ref and out parameters do not allow type variation. So, to pass a variable to a method expecting an out object parameter, that variable must be declared as object.
From the specification (§10.6.1.2 and §10.6.1.3)
When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
See: Why do ref and out parameters not allow type variation? for some insight into why.
Bonus question: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T)?
I'm going to turn it back around on you. Why are you doing this? If you are invoking MyType<T>.TryParse as, say, MyType<int>.TryParse, why not call Int32.TryParse directly? What is this extra layer buying you?
I know this is somewhat low-tech, but I have had the same problem, where I solved it by making a Dictionary<Type, Parser> containing the individual parsers. I will be interested in what answers this questions bring.
Regards,
Morten
Current solution
The current solution I use at work is based on dynamic dispatch, that is, the keyword dynamic as defined on C# 4.0.
The code is something like (from memory) :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// Because m_p is dynamic, the function to be called will
// be resolved at runtime, after T is known...
m_p.DoTryParse(p_input, out p_output) ;
}
// The dynamic keyword means every function called through
// m_p will be resolved at runtime, at the moment of the call
private dynamic m_p = new Parser() ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private void DoTryParse(string p_input, out double p_output)
{ /* Do something and return the right value */ }
private void DoTryParse(string p_input, out int p_output)
{ /* Do something and return the right value */ }
// etc.
private void DoTryParse<T>(string p_input, out T p_output)
{
// fallback method... There are no dedicated method for T,
// so p_output becomes the default value for T
p_output = default(T) ;
}
}
The elegant part is that it can't fail (the fallback function will be called, if none with a better signature match is found), and that it follows a simple pattern (overload the function).
Of course, the real-life, production code is somewhat different, and more complicated because, with but one public static method, I want to :
parse both reference objects (classes) and value objects (structs)
parse enums
parse nullable types
I want to offer the user the possibility to derive from Parser to offer its own overloads in addition to the default ones
But I guess the use of dynamic in the current solution is, in the end, the same thing as doing reflection as done in the original answer below. Only the "notation" changes.
Conclusion, I now have the following method :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// etc.
}
}
which is able to parse anything, including in situations where T is not known at compile time (because the code is generic).
Original answer
Jason's answer was right about the first question (about the compiler errors). Still, I had no solution to my problem (dispatching from a generic method to non-generic methods according to the runtime generic type T).
I tried LukeH's answer, but it didn't work: The generic method is always called, no matter what (even when removing the out qualifier of the second parameter).
Morten's answer is the most sane one that should works, but it doesn't make use of reflection.
So, to solve my own problem, I used reflection. This needs the rewriting of the generic TryParse method:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value = default(T);
// search for the method using reflection
System.Reflection.MethodInfo methodInfo = typeof(Parser).GetMethod
(
"TryParse",
new System.Type[] { typeof(string), typeof(T).MakeByRefType() }
);
if (methodInfo != null)
{
// the method does exist, so we can now call it
var parameters = new object[] { p_value, value };
methodInfo.Invoke(null, parameters);
value = (T)parameters[1];
}
else
{
// The method does not exist. Handle that case
}
}
}
I have the source code available if needed.
This problem intrigued me, so I did some research and found a nice thing by Paul Madox. This seems to do the trick.
public static T SafeParseAndAssign<T>(string val) where T: new()
{
try
{
T ValOut = new T();
MethodInfo MI = ValOut.GetType().
GetMethod("Parse", new Type[] { val.GetType() });
return (T)MI.Invoke(ValOut, new object[] { val });
}
catch
{
// swallow exception
}
return default(T);
}