为了账号安全,请及时绑定邮箱和手机立即绑定

运算符=不能应用于C#中的泛型类型吗?

运算符=不能应用于C#中的泛型类型吗?

C#
慕仙森 2019-06-19 16:07:26
运算符=不能应用于C#中的泛型类型吗?根据文件==运算符MSDN,对于预定义的值类型,如果操作数的值相等,则相等运算符(=)返回true,否则为false。对于字符串以外的引用类型,如果其两个操作数引用同一个对象,则=返回true。对于字符串类型,=比较字符串的值。用户定义的值类型可以重载=操作符(请参阅操作符)。用户定义的引用类型也可以,尽管默认情况下,对于预定义和用户定义的引用类型,其行为都如上文所述。那么,为什么这个代码段无法编译呢?bool Compare<T>(T x, T y) { return x == y; }我知道错误运算符‘=’不能应用于‘T’和‘T’类型的操作数..我不知道为什么,据我所知==操作符是否为所有类型预定义?编辑:谢谢各位。一开始,我没有注意到这条语句只是关于引用类型的。我还认为,对所有值类型都提供了逐点比较,我现在知道的是不对,是这样。但是,如果我使用的是引用类型,==运算符使用预定义的引用比较,或者如果类型定义了,它会使用操作符的重载版本吗?编辑2:经过反复试验,我们了解到==运算符在使用无限制泛型类型时将使用预定义的引用比较。实际上,编译器将对受限类型参数使用它能找到的最佳方法,但不会进一步研究。例如,下面的代码将始终打印true,即使当Test.test<B>(new B(), new B())称为:class A { public static bool operator==(A x, A y) { return true; } }class B : A { public static bool operator==(B x, B y) { return false; } } class Test { void test<T>(T a, T b) where T : A { Console.WriteLine(a == b); } }
查看完整描述

3 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

“.在默认情况下,对于预定义和用户定义的引用类型,行为都如上文所述。”

类型T不一定是引用类型,所以编译器不能这样做。

但是,这将编译,因为它更显式:

    bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }

接着补充一个问题,“但是,如果我使用的是引用类型,那么=操作符是使用预定义的引用比较,还是使用重载版本的操作符(如果是类型定义的话)?”

我原以为=on Generics会使用重载版本,但下面的测试说明的不是这样。有趣.。我很想知道为什么!如果有人知道,请分享。

namespace TestProject{
 class Program
 {
    static void Main(string[] args)
    {
        Test a = new Test();
        Test b = new Test();

        Console.WriteLine("Inline:");
        bool x = a == b;
        Console.WriteLine("Generic:");
        Compare<Test>(a, b);

    }


    static bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }
 }

 class Test
 {
    public static bool operator ==(Test a, Test b)
    {
        Console.WriteLine("Overloaded == called");
        return a.Equals(b);
    }

    public static bool operator !=(Test a, Test b)
    {
        Console.WriteLine("Overloaded != called");
        return a.Equals(b);
    }
  }}

输出量

内联:重载=调用

通用:

按任意键继续。....

后续行动2

我想指出的是,将我的比较方法改为

    static bool Compare<T>(T x, T y) where T : Test
    {
        return x == y;
    }

导致调用重载=操作符。我想没有指定类型(作为哪里),编译器不能推断它应该使用重载运算符.尽管我认为它有足够的信息来做出这个决定,即使没有指定类型。


查看完整回答
反对 回复 2019-06-19
?
侃侃无极

TA贡献2051条经验 获得超10个赞

正如其他人所说,只有当T被限制为引用类型时,它才会起作用。在没有任何约束的情况下,您可以使用NULL进行比较,但只能使用NULL进行比较,对于非空值类型,这种比较始终是假的。

与其调用等于,不如使用IComparer<T>-如果你没有更多的信息EqualityComparer<T>.Default是个不错的选择:

public bool Compare<T>(T x, T y){
    return EqualityComparer<T>.Default.Equals(x, y);}

除了其他任何东西,这避免了拳击/铸造。


查看完整回答
反对 回复 2019-06-19
?
撒科打诨

TA贡献1934条经验 获得超2个赞

总体而言,EqualityComparer<T>.Default.Equals应该用任何实现IEquatable<T>,或者说这是明智的Equals执行。

但是,如果,==Equals由于某种原因而实现不同,那么我的工作是泛型运算符应该是有用的;它支持操作者版本(除其他外):

  • 相等(T值1,T值2)
  • 不相等(T值1,T值2)
  • 大于(T值1,T值2)
  • LessThan(T值1,T值2)
  • (T值1,T值2)
  • LessThanOrequue(T值1,T值2)


查看完整回答
反对 回复 2019-06-19
  • 3 回答
  • 0 关注
  • 812 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信