简体   繁体   中英

C#/Fixing Operators for Generics

I tried to apply operators on Generics (for my example,multiplication)

    public static List<TOutput> Conversion<TOutput>(List<TInput> input)
    {
        List<TOutput> outList = new List<TOutput>();
        foreach(TInput tinput in input)
        {
            double dbl = tinput *tinput;
            outList.Add(dbl);

        }
        return outList;

    }

Any workaround for fixing it?

Not possible without reflecting upon the type. There is some code that does this available as part of MiscUtil .

This is now possible in C# 11 / .NET 7 (or above):

public static List<TOutput> Conversion<TInput, TOutput>(List<TInput> input)
    where TInput : IMultiplyOperators<TInput, TInput, TOutput>
{
    List<TOutput> outList = new List<TOutput>();
    foreach (TInput tinput in input)
    {
        TOutput product = tinput * tinput;
        outList.Add(product);

    }
    return outList;
}

The compiler shouldn't allow you to assign a double to an unknown type:

outList.Add(dbl);

For all it knows, you could be trying to assign a dbl to a type of FluxCapacitor. Your code is trying to accomplish two incompatible things: to return a list of generic (unknown) type, and 2) to force that type to be a double. This doesn't make sense, which is why you're having difficulty. You can use reflection (as Porges pointed out with an excellent link) to solve this dynamically, but you really need to ask yourself: why are you trying to assign a floating point number to a class that has an unknown type? The calling code could be asking for a result of List<bool> . How much sense would it make to try to assign

double foo = 1.5;
bool bar = foo;

? Zero. You can make the compiler do anything with enough somersaults, but you need to reevaluate the purpose of your routine, why you're trying to put a specific datatype into a generic one, and whether or not this routine needs to return a generic list.

The "MiscUtil" answer (already accepted) would be my first choice ;-p

You might also consider LINQ at the caller:

var prodList = originalList.Select(x=>x*x).ToList();

Since the caller knows the type (assuming it isn't itself generic, this should work.

Just for completeness, another option here (in 4.0) is dynamic :

public static List<TOutput> Conversion<TOutput>(List<TInput> input)
{
    List<TOutput> outList = new List<TOutput>();
    foreach(TInput tinput in input)
    {
        TOutput square = (dynamic)tinput * (dynamic)tinput;
        outList.Add(square);

    }
    return outList;
}

You could use a cached lambda to do your calculation (and/or conversion).

This doesn't require the DLR or the dynamic keyword, so it's perfectly usable in C# 3.0

static class Squarer<T>
{
    private static readonly Func<T, T> _square;
    static Squarer()
    {
        ParameterExpression x = Expression.Parameter(typeof(T), "x");
        _square = Expression.Lambda<Func<T, T>>(
            Expression.Multiply(x, x),
            x).Compile();
    }

    public static T Square(T value)
    {
        return _square.Invoke(value);
    }
}

Console.WriteLine(Squarer<double>.Square(1234.5678));
Console.WriteLine(Squarer<decimal>.Square(1234.5678m));
Console.WriteLine(Squarer<int>.Square(1234));

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