Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 编写不是容器的泛型类?[丙]_C#_Generics_Comparison_Operator Overloading_Operators - Fatal编程技术网

C# 编写不是容器的泛型类?[丙]

C# 编写不是容器的泛型类?[丙],c#,generics,comparison,operator-overloading,operators,C#,Generics,Comparison,Operator Overloading,Operators,目标: 我一直在尝试用C编写一个通用的helper/utility类,它表示一个数字的边界检查范围 其思想是,用户可以通过定义最小值和最大值(例如,从0到10、从-15到3、从-7到-2等)来创建连续的数字范围。。该范围还包含一个当前值,并根据上限/下限检查该值。如果当前值大于最大值或小于最小值,则会将其覆盖或环绕。我希望这个类是泛型的,这样客户机就可以为他们的用例选择合适的类型/大小/精度 以下是我目前掌握的情况: public class Range<T> where T : I

目标:

我一直在尝试用C编写一个通用的helper/utility类,它表示一个数字的边界检查范围

其思想是,用户可以通过定义最小值和最大值(例如,从0到10、从-15到3、从-7到-2等)来创建连续的数字范围。。该范围还包含一个当前值,并根据上限/下限检查该值。如果当前值大于最大值或小于最小值,则会将其覆盖或环绕。我希望这个类是泛型的,这样客户机就可以为他们的用例选择合适的类型/大小/精度

以下是我目前掌握的情况:

public class Range<T> where T : IComparable<T> {

    private T value;
    private T min;
    private T max;

    private bool wrap;

    public Range ( T minimumValue, T maximumValue, T initialValue, bool tempWrap = false ) {
        value = initialValue;
        min = minimumValue;
        max = maximumValue;
        wrap = tempWrap;

        LimitBounds ();
    }

    private void LimitBounds () {
        if( wrap != true ) {
            if ( value > max ) { value = max; }
            else if ( value < min ) { value = min ; }
        }
        else {
            T wrapAmount = 0;

            if ( value > max ) { 
                wrapAmount = value - max;
                value = min + wrapAmount;
            }
            else if ( value < min ) {
                wrapAmount = min - value;
                value = max - wrapAmount;
            }
        }
    }

    public T GetValue() {
        return value;
    }

    public void SetValue(T tempValue) {
        value = tempValue;
        LimitBounds ();
    }

    public void Increment() {
        value++;
        LimitBounds ();
    }

    public void Decrement() {
        value--;
        LimitBounds ();
    }

    public bool Equals(Range<T> tempRange)
    {
        return (value == tempRange.value);
    }

    public static bool operator > (Range<T> r1, Range<T> r2)
    {
        return (r1.value > r2.value);
    }

    public static bool operator < (Range<T> r1, Range<T> r2)
    {
        return (r1.value < r2.value);
    }

    public static Range<T> operator ++ ( Range<T> r ) {
        r.Increment ();
        return r;
    }

    public static Range<T> operator -- ( Range<T> r ) {
        r.Decrement ();
        return r;
    }
}
。。我的大多数操作符重载都有类似的错误。我认为,如果我确保我的类处理的类型实现“Comparable”,则可以重载比较运算符。我显然做错了什么,但我不确定我需要做什么

如果它简化了事情,这个类实际上只需要处理纯数值/类型byte、short、int、float等

更新编辑1:

如下所示,通过切换到这些函数中的CompareTo,我能够消除由比较操作引起的一系列编译错误:

    public bool Equals(Range<T> tempRange)
    {
        return (value.CompareTo(tempRange.value) == 0);
    }

    public static bool operator > (Range<T> r1, Range<T> r2)
    {
        return (r1.value.CompareTo (r2.value) > 0);
    }

    public static bool operator < (Range<T> r1, Range<T> r2)
    {
        return (r1.value.CompareTo (r2.value) < 0);
    }
我还添加了“struct”约束。不过,我仍然不确定该从这里走到哪里。我的代码仍然无法编译,因为我一直在使用各种加法、减法、增量和减量运算符。我尝试添加byte、short、int和float作为附加的类型约束,但没有成功,这给了我一个编译时错误

我在这里有什么选择?因为这个类只处理数字的范围,基本上只处理各种大小的整数[字节、短、整数、长]和浮点小数,而不是可为null或引用类型,所以我可以使用其他约束来实现这一点吗?我是否必须围绕实现自定义“INumber”接口的基本数据类型创建一组包装器类


或者这是对泛型类的滥用,我应该为不同的类型创建一组独立的范围类?有可能生成一个实现我想要的行为类型的泛型类吗?

错误的原因是编译器无法确保t的类型将正确地重载所有这些运算符。而且也没有这样的约束来强制它

例如,使用CompareTo方法代替比较运算符,而不是

value > max
使用

对于小于:value.CompareTomax<0的等式,value.CompareTomax==0

有关更多信息,请参阅文档

递增运算符和递减运算符更复杂。您可以为您的类型编写不同的重载以递增和递减,并为当前类型调用适当的重载


最后一点要注意的是,如果您计划将此方法仅用于byte、int、double等结构类型,则可能需要添加结构约束。

对于泛型,您无法执行算术运算,因为直到编译时,您才知道其类型

所以你可以做两件事:

如果总是使用long、decimal等类型,那么将泛型类仅限于这些类型

运算符重载


这就是使用运算符和泛型的问题,因为很多代码无法编译。例如,value++或value-。编译器不知道t是否实现了特定的运算符。不幸的是,还没有对操作符的约束,所以您只剩下一些非常非通用的解决方案,或者您可以使用dynamic作为解决方案

请注意,这是绕过编译时检查。对于在运行时会中断的类型,您的代码可以很好地编译

public void Increment()
{
    dynamic x = value;
    x++;
    value = x;
}

运算符不是虚拟的,因此不能与泛型类型一起使用。使用为受约束类型定义的适用方法。请记住,泛型不是模板,也不会发生文本替换。因此,代码必须对泛型类本身中由T表示的所有类型都有效。当您不知道类型时,如何在方法中执行value++和value-递增和递减?Duh!我懂了。。谢谢各位。最初我是用Short编写这个类的,但在我完成这项工作后,我决定让它更通用更有用/更灵活。我考虑过制作一些类,如“IntRange”、“ShortRange”、“FloatRange”等。我想当我弄明白后,这会好得多。我以前用过别人的仿制药,但这是我第一次尝试写一个我认为value.CompareTomax>1应该大于0。当然,如果T是引用类型,而value是空引用,它可能会爆炸。另一个解决方案是如果Comparer.Default.Comparevalue,max>0{…}。另一方面,如果您知道您不会将其用于引用类型,则可以
将constriant指定为其中T:struct,i可比较。关于平等,考虑是否平等不是你想要的方法。如果您限制为IEquatable,则在某些情况下可以避免装箱和类型检查,尽管它们非常快。谢谢大家的帮助。在添加约束并切换到CompareTo(在适用的情况下)之后,我成功地使通用比较工作起来!不幸的是,我仍然有大量的加法、减法、增量和减量操作会引发编译错误。。我还添加了一个结构约束。我可以使用不同的泛型约束来帮助获得+、-、++和-工作吗?或者尝试使用泛型来实现这类功能是不可能/不可取的吗?我应该放弃,只做一些特定的系列课程吗?ByteRange、IntRange、FloatRange等。。或者对我希望这个类处理的每种类型使用特定的约束?Byte、Short、Int、Float、Double等作为约束。@MrKatSwordfish它们应该有参数。像void Incrementref int i一样,您需要检查typeof T并将其传递给适当的函数cando。。操作员超载?谢谢。如果可能的话,我想避免这种情况;在可能的情况下,将运行时错误的风险降至最低似乎是个好主意。我更希望我的代码在编译时失败,而不是意外崩溃!:]我发现这比我想象的要困难得多。。haha@MrKatSwordfish理解。当我在项目中这样做时,我使用了结构约束和清晰的注释,以最大限度地减少误用的机会。
value.CompareTo(max) > 0
public void Increment()
{
    dynamic x = value;
    x++;
    value = x;
}