问题
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.
回答1:
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).
回答2:
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)
}
回答3:
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
}
}
来源:https://stackoverflow.com/questions/59519621/c-sharp-is-there-any-better-way-to-use-switch-case-if-else-on-generic-types