简体   繁体   中英

How to use value types in generics

I have the following code:

public class Class1
{
    void ValueSpecific(string arg)
    {
        // do string stuff
    }
    void ValueSpecific(int arg)
    {
        // do int stuff
    }
    void ValueSpecific(float arg)
    {
        // do float stuff
    }
    void ValueGeneric(string arg)
    {
        // do stuff
        ValueSpecific(arg);
        // do more stuff
    }
    void ValueGeneric(int arg)
    {
        // do stuff
        ValueSpecific(arg);
        // do more stuff
    }
    void ValueGeneric(float arg)
    {
        // do stuff
        ValueSpecific(arg);
        // do more stuff
    }
    void Main(string s, int i, float f)
    {
        ValueGeneric(s);
        ValueGeneric(i);
        ValueGeneric(f);
    }
}

This works but the bodys of all three overloads of ValueGeneric are identical. I want to amalgamate them into one method, which would look something like:

void ValueGeneric<T>(T arg) where T: string, float, int
{
    // do stuff
    ValueSpecific(arg);
    // do more stuff
}

but this, of course, is not valid C#. The best I can come up with is:

void ValueGeneric(object arg)
{
    // Do stuff
    if (arg is int)
    {
        ValueSpecific((int)arg);
    }
    else if (arg is string)
    {
        ValueSpecific((string)arg);
    }
    else if (arg is float)
    {
        ValueSpecific((float)arg);
    }
    else
    {
        Debug.Assert(false, "Invalid type)
    }
    // Do more stuff
}

but this seems very inelegant. I'd appreciate any suggestions. (While I would be interested in any solutions, one supported by .NET3.5 would be best, as that is what I am using.)

Assuming you're doing the same stuff before and after in all of your overloads, you can apply the usual approach of factoring out what is different in the code and parameterize them. The only things that change are the argument that is passed in and the action that you perform on that argument. Pass them both in.

static void ValueGeneric<T>(T arg, Action<T> action)
{
    // do stuff
    action(arg);
    // do more stuff
}

Then call the generic method using the appropriate action (your ValueSpecific overloads will resolve itself nicely).

ValueGeneric(s, ValueSpecific);
ValueGeneric(i, ValueSpecific);
ValueGeneric(f, ValueSpecific);

From what I've seen of other, large .NET projects, you could include both the specific and generic overloads. If a specific overload doesn't exist, they'll just use the generic version instead:

void ValueGeneric(int i);
void ValueGeneric(string s);
void ValueGeneric(float f);
void ValueGeneric<T>(T t);

By the structure of the code you posted, it seems like you want to do something to all the types before and after the contents of ValueSpecific , so you could make private PreValueGeneric and PostValueGeneric methods that all the ValueGeneric overloads call at the beginning and end to avoid code duplication between the overloads.

Have you consider using an extension method for each type? It could be an alternative for this case.

you can define a class and define that methods. Like:

namespace ExtensionMethods
{
    public static class Class1
    {
        static void ValueSpecific(this string arg)
        {
            // do string stuff
        }
        static void ValueSpecific(this int arg)
        {
            // do int stuff
        }  
    }
}

and then, when you want to use them, just do

Int32 myIntVar = 20;
myIntVar.ValueSpecific();
String myStringVar = "hi",
myStringVar.ValueSpecific();

you will have to add

using ExtensionMethods;

only declare the methods and use them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM