使用泛型在类上的值类型之间进行转换

6 c# generics

在函数的这一部分(.NET 2.0)中:

public void AttachInput<T>(T input) where T : struct
{
    if (input is int)
    {
        Inputs.Add((int)input);
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器显示错误"无法将类型'T'转换为'int'.
所以,我使用Convert.ToInt32()哪个工作 - 但是它是否包装input到一个对象?有更好的解决方案吗?谢谢

编辑1:取消与问题相关的不必要的东西

编辑2:深入研究泛型,在我看来,Convert.ToInt32当T已经是一个int时,没有对一个对象的装箱,而它的int重载就是被调用的那个.

如果这是真的,那么这些Convert方法在我看来是最好的选择

Dan*_*ker 5

对于类型安全和避免装箱,您唯一的选择是输入类型的特定重载int:

public void AttachInput(int input)
{
    Inputs.Add(input);
}
Run Code Online (Sandbox Code Playgroud)

更新:

OP用一个理论更新了这个问题:

深入研究泛型,在我看来,当T已经是一个int时,Convert.ToInt32对一个对象没有装箱,而它的int重载就是被调用的那个.

这是不对的,一个简单的测试可以证明它.假设我们编写自己的一组重载只是为了检测哪一个被调用:

public static class OverloadTest
{
    public static void Foo(int x)
    {
        Console.WriteLine("Foo(int)");
    }

    public static void Foo(bool x)
    {
        Console.WriteLine("Foo(bool)");
    }

    public static void Foo(object x)
    {
        Console.WriteLine("Foo(object)");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们编写一个通用方法来模拟问题中的那个:

static void CallTheRightFoo<T>(T value) where T : struct
{
    OverloadTest.Foo(value);
}
Run Code Online (Sandbox Code Playgroud)

理论上,因为CLR/JIT将为每种值类型生成特定版本的方法,所以它可以选择特定的过载,int因为它可用.

所以这是测试:

struct Test { } // in order to test a user-defined value type

static void Main(string[] args)
{
    CallTheRightFoo(1);
    CallTheRightFoo(true);
    CallTheRightFoo(new Test());
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Foo(object)
Foo(object)
Foo(object)
Run Code Online (Sandbox Code Playgroud)

要将其与Convert.ToInt32您的通用代码相关联,您将始终调用接受的重载,object因此该值将被装箱,然后必须在内部取消装箱Convert.ToInt32(这也必须先检查它是什么类型).

虽然重申所有这一点背后的重要一点:虽然与不这样做相比,装箱/拆箱比较昂贵,但与你的代码所做的任何实际工作相比,它的成本可能微不足道.所以我不会过分担心它的成本,直到你可以证明它是使用你的库的应用程序的真实模型的真正负担.