C#泛型:如何在泛型类中使用x.MaxValue/x.MinValue(int,float,double)

Pyg*_*gmy 7 c# generics floating-point double int

我正在使用WPF扩展工具包(http://wpftoolkit.codeplex.com/).

它有一个很好的NumericUpDown控件,我想使用它,但在内部它使用双精度 - 这意味着它使用double.MinValue和double.MaxValue.

我想使用相同的控件,但我需要一个通用版本 - 对于int它需要使用int.MaxValue/MinValue,浮动float.MaxValue/MinValue等(我想你明白:))

所以我想将NumericUpDown复制到GNumericUpDown,其中T将是Type ..但这不起作用,因为泛型Type没有MinValue/MaxValue.通常我会使用'where'子句来指定基类型,但是这不能用作afaik,没有定义'MinValue'和'MaxValue'的通用接口.

有没有办法用泛型来解决这个问题,还是我真的需要复制/粘贴/搜索并替换每种类型的原始NumericUpDown?

Jon*_*eet 9

好吧,既然你可以在执行时类型得到,你可以依靠的事实,所有的数字类型在.NET中有MinValueMaxValue领域,并与反思阅读.它不会非常好,但很容易做到:

using System;
using System.Reflection;

// Use constraints which at least make it *slightly* hard to use
// with the wrong types...
public class NumericUpDown<T> where T : struct,
    IComparable<T>, IEquatable<T>, IConvertible
{
    public static readonly T MaxValue = ReadStaticField("MaxValue");
    public static readonly T MinValue = ReadStaticField("MinValue");

    private static T ReadStaticField(string name)
    {
        FieldInfo field = typeof(T).GetField(name,
            BindingFlags.Public | BindingFlags.Static);
        if (field == null)
        {
            // There's no TypeArgumentException, unfortunately. You might want
            // to create one :)
            throw new InvalidOperationException
                ("Invalid type argument for NumericUpDown<T>: " +
                 typeof(T).Name);
        }
        return (T) field.GetValue(null);
    }
}

class Test
{
    static void Main()
    {
        Console.WriteLine(NumericUpDown<int>.MaxValue); 
        Console.WriteLine(NumericUpDown<float>.MinValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您使用不合适的类型,我试图尽可能强制编译时错误...但它不会万无一失.如果您设法找到具有所有正确接口但没有MinValueMaxValue字段的结构,那么任何使用该NumericUpDown类型的尝试都将导致抛出异常.


Jul*_*iet 8

OP对另一个答案做出了评论:

我想在我的XAML中使用这些控件.我的想法是创建一个通用版本,然后创建像NumericUpDownInt这样的空类:GNumericUpDown {}这将是要走的路,还是有更好/更清洁的方式来获取你的知识

如果您要去那条路线,那么直接通过最小值和最大值:

class abstract GenericNumericUpDown<T>
{
    public GenericNumericUpDown(T min, T max) { ... }
}

class NumericUpDownInt : GenericNumericUpDown<int>
{
    public NumericUpDownInt() : base(int.MinValue, int.MaxValue) { ... }
}

class NumericUpDownFloat : GenericNumericUpDown<float>
{
    public NumericUpDownFloat() : base(float.MinValue, float.MaxValue) { ... }
}

class NumericUpDownDouble : GenericNumericUpDown<double>
{
    public NumericUpDownDouble() : base(double.MinValue, double.MaxValue) { ... }
}
Run Code Online (Sandbox Code Playgroud)