简体   繁体   中英

Using C# generics to create a mapper method with different return types

I am trying to create a method to map int to string and string to int. I had the idea to do it in a single method, but not really sure if this is possible.

I got this far:

class MappingWithGenerics
    {
        [Test]
        public void IntToString()
        {
            string actual = Map<int, string>(1);
            Assert.AreEqual("1", actual);
        }

        [Test]
        public void StringToInt()
        {
            int actual = Map<string, int>("1");
            Assert.AreEqual(1, actual);
        }

        public TOut Map<Tin, TOut>(Tin element)
        {
            if(element.GetType() == typeof(int))
                return element.ToString();
            return Convert.ToInt32(element);
        }
    }

this gives compilation errors.

Cannot implicitly convert type 'int' to 'TOut'

Cannot implicitly convert type 'string' to 'TOut'

Any idea how I could implement the Map method?

Generics are for when you want the same functionality across a bunch of different types. In this case, you're dealing with two specific types and you want different functionality between them. Generics aren't really what you want, especially when you can do the same thing with simple method overloading:

class MappingWithoutGenerics
{
    public string Map(int x)
    {
        return x.ToString();
    }

    public int Map(string s)
    {
        return Convert.ToInt32(s);
    }
}

The reason that your code does not compile is that you coded a generic method with only two specific types in mind. You can shoehorn this into a generic function with conversion to object , but this is not a good idea.

You can implement the desired functionality using the Convert class, like this:

public static TOut Map<Tin, TOut>(Tin element) {
    return (TOut)Convert.ChangeType(element, typeof(TOut));
}

Your test methods will work without a change. However, the method will be capable of conversions beyond string -> int and int -> string : you will be able to convert between any pair of types supported by Convert.ChangeType method.

Demo.

You can implement the method like this:

    public TOut Map<Tin, TOut>(Tin element)
    {
        object outValue;
        if(element.GetType() == typeof(int))
            outValue = element.ToString();
        else
            outValue = Convert.ToInt32(element);
        return (TOut)outValue;
    }

But I really wonder why do you need such a method. I'm sure there is better way to solve your broader problem.

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