简体   繁体   English

Generics 的 C#/修复运算符

[英]C#/Fixing Operators for Generics

I tried to apply operators on Generics (for my example,multiplication)我尝试在 Generics 上应用运算符(例如,乘法)

    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 . 有一些代码可以作为MiscUtil的一部分提供

This is now possible in C# 11 / .NET 7 (or above):这现在可以在 C# 11 / .NET 7(或以上):

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: 编译器不应允许您将double赋值为未知类型:

outList.Add(dbl); outList.Add(DBL);

For all it knows, you could be trying to assign a dbl to a type of FluxCapacitor. 尽管如此,您可能会尝试将dbl分配给一种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. 您的代码正在尝试完成两个不兼容的事情:返回通用(未知)类型的列表,以及2)强制该类型为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? 您可以使用反射(如Porges指出的优秀链接)动态解决这个问题,但您确实需要问自己:为什么要尝试将浮点数分配给具有未知类型的类? The calling code could be asking for a result of List<bool> . 调用代码可能要求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 “MiscUtil”答案(已被接受)将是我的第一选择;-p

You might also consider LINQ at the caller: 您也可以在调用者处考虑LINQ:

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 : 为了完整起见,这里的另一个选项(在4.0中)是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). 您可以使用缓存的lambda进行计算(和/或转换)。

This doesn't require the DLR or the dynamic keyword, so it's perfectly usable in C# 3.0 这不需要DLR或动态关键字,因此它在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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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