C#相等性比较

本文阐述C#中相等性比较,其中主要集中在下面两个方面

==和!=运算符,什么时候它们可以用于相等性比较,什么时候它们不适用,如果不使用,那么它们的替代方式是什么?

什么时候,需要自定一个类型的相等性比较逻辑

在阐述相等性比较,以及如何自定义相等性比较逻辑之前,我们首先了解一下值类型比较和引用类型比较

值类型比较对比引用类型比较

C#中的相等性比较有两种:

  • 值类型相等,两个值在某种场景下相等
  • 引用类型相等,两个引用指向同一个对象

默认情况下,

  • 值类型使用值类型相等
  • 引用类型使用引用相等

实际上,值类型只能使用值相等(除非值类型进行了装箱操作)。看一个简单的例子(比较两个数字),运行的结果为True

int x = 5, y = 5;
Console.WriteLine(x == y);

默认地,引用类型使用引用相等。比如下面的例子:返回False

object x = 5, y = 5;
Console.WriteLine(x == y);

如果x和y指向同一个对象,那么将返回True:

object x = 5, y = x;
Console.WriteLine(x == y);

相等性的标准

下面三个标准用于实现相等性比较:

  • ==和!=运算符
  • object中的虚方法Equals
  • IEquatable<T>接口

下面我们来分别阐述

1. ==和!=运算符

使用==和!=的原因是它们是运算符,它们通过静态函数实现相等性比较。因此,当你使用==或!=时,C#在编译时就决定了所比较的类型,而且不会执行任何虚方法(Object.Equals)。这是大家所期望的相等行比较。比如在第一个数字比较的例子中,编译器在编译时就决定了执行==运算的类型是int类型,因为x和y都是int类型。

而第二个例子,编译器决定执行==运算的类型是object类型,因为object是类(引用类型),因此对象的==运算符采取引用相等去比较x和y。那么结果就返回False,这是因为x和y指向堆上不同的对象(被装箱的int)

 

2. Object.Equals虚方法

为了正确地比较第二个例子中的x和y,我们可以使用Equals虚方法。System.Object中定义了Equals虚方法,它适用于所有类型

object x = 5, y = 5;
Console.WriteLine(x.Equals(y));

Equals在程序运行时决定比较的类型--根据对象的实际类型进行比较。在上面的例子中,会调用Int32的Euqals方法,该方法使用值相等进行比较,所以上面的例子返回True。如果x和y是引用类型,那么调用引用相等进行比较;如果x和y是结构类型,那么Equals会调用结构每个成员对应类型的Equals方法进行比较。

看到这里,你可能会想,为什么C#的设计者不把==设计成virtaul,从而使其与Equals一样,以避免上诉缺陷。这是因为:

  • 如果第一个运算对象是null,Equals方法会抛出NullReferenceException异常;而静态的运算符则不会
  • 因为==运算符在编译时决定了比较类型(静态解析比较类型),那么它的执行就非常快。这也就使得编写大量运算代码去执行相等性比较时对性能不会带来太大的影响
  • 有时候,==和Equals适用于不同的场景的相等性比较。(后续的内容会涉及)

简而言之,复杂的设计反映了复杂的场景:相等的概念涉及到许多场景。

 

而Euqals方法,适用于比较两个未知类型的对象,下面的这个方法就适用于比较任何类型的两个对象:

public static bool AreEqual(object obj1, object obj2)
{
    return obj1.Equals(obj2);
}

但是,该函数不能处理第一个参数是null的情形,如果第一个函数是null,你会得到NullReferenceException异常。因此我们需要对该函数进行修改:

public static bool AreEqual(object obj1, object obj2)
{
    if (obj1 == null)
        return obj2 == null;
    return obj1.Equals(obj2);
}

 

object的静态Equals方法

object类还定义了一个静态Equals方法,它的作用与AreEquals方法一样。

public static bool Equals(Object objA, Object objB)
{
    if (objA==objB) {
        return true;
    }
    if (objA==null || objB==null) {
        return false;
    }
    return objA.Equals(objB);
}

这样就可以对编译时不知道类型的null对象进行安全地比较。

object x = 5, y = 5;
Console.WriteLine(object.Equals(x, y)); // -> True
x = null;
Console.WriteLine(object.Equals(x, y)); // -> False
y = null;
Console.WriteLine(object.Equals(x, y)); // -> True

Console.WriteLine(x.Equals(y)); // -> NullReferebceException, because x is null

请注意,当编写Generic类型时,下面的代码将不能通过编译(除非把==或!=运算符替换成Object.Equals方法的调用):

public class Test<T> : IEqualityComparer<T>
{
    T _value;

    public void SetValue(T newValue)
    {
        // Operator '!=' cannot be applied to operands of type 'T' and 'T'
        // it should be : if(!object.Equals(newValue, _value))
        if (newValue != _value)
            _value = newValue;
    }
}

object的静态ReferenceEquals方法

有时候,你需要强行比较两个引用是否相等。这个时候,你就需要使用object.ReferenceEquals:

internal class Widget 
{
    public string UID { get; set; }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return this == null;

        if (!(obj is Widget))
            return false;
        Widget w = obj as Widget;
        return this.UID == w.UID;
    }

    public override int GetHashCode()
            {
                return this.UID.GetHashCode();
            }

    public static bool operator  == (Widget w1, Widget w2)
            {
                return w1.Equals(w2);
            }

    public static bool operator !=(Widget w1, Widget w2)
            {
                return !w1.Equals(w2);
            }
}

static void Main(string[] args)
{

    Widget w1 = new Widget();
    Widget w2 = new Widget();
    Console.WriteLine(w1==w2); // -> True
    Console.WriteLine(w1.Equals(w2)); // -> True
    Console.WriteLine(object.ReferenceEquals(w1, w2)); // -> False 

    Console.ReadLine();
}
Basic ReferenceEquals

 

之所以调用ReferenceEquals方法,这是因为自定义类Widget重写了object类的虚方法Equals;此外,该类还重写了操作符==和!=,因此执行==时操作也返回True。所以,调用ReferenceEquals可以确保返回引用是否相等。

3. IEquatable<T>接口

调用object.Equals方法实际上对进行比较的值类型进行了装箱操作。在对性能有较高要求的场景,那么就不适合使用这种方式。从C#2.0开始,通过引入IEquatable<T>接口来解决这个问题

public interface IEquatable<T>
{
    bool Equals(T other);
}

当实现IEquatable接口之口,调用接口方法就等同于调用objet的虚方法Equals,但是接口方法执行地更快(不需要类型转换)。大多数.NET基本类型都实现了IEquatable<T>接口,你还可以为Generic类型添加IEquatable<T>限制

internal class Test<T> where T : IEquatable<T>
{
    public bool IsEqual(T t1, T t2)
    {
        return t1.Equals(t2);
    }
}

如果,我们移除IEquatable<T>限制,Test<T>类仍可以通过编译,但是t1.Equals(t2)将使用object.Equals方法。

4. 当Equals结果与==的结果不一致

在前面的内容中,我们已经提到有时候,==或equals适用于不同的场景。比如:

double x = double.NaN;
Console.WriteLine(x == x); // False
Console.WriteLine(x.Equals(x)); // True

这是因为double类型的==运算符强制NaN不等于其他任何值,即使另外一个NaN。从数学的角度来讲,两个确实不相等。而Equals方法,因为具有对称性,所以x.Equals(x)总返回True。

集合与字典正是依赖于Equals的对称性,否则就不能找到已经保存在集合或字典中的元素。

对于值类型而言,Equals和==很少出现不同的相等性。而在引用类型中,则比较常见。一般地,引用类型的创建者重写Equals方法执行值相等比较,而保留==执行引用相等比较。比如StringBuilder类就是这样的:

StringBuilder buffer1 = new StringBuilder("123");
StringBuilder buffer2 = new StringBuilder("123");
Console.WriteLine(buffer1 == buffer2); // False
Console.WriteLine(buffer1.Equals(buffer2)); // True

 

比较自定义类型

回顾一下默认的比较行为

  • 值类型使用值相等
  • 引用类型使用引用相等

进一步,

  • 结构类型的equals方法会根据每个字段的类型进行相等行比较

有时候,在创建类型时,需要重写上述行为,一般在下面两种情形下需要重写:

  • 更改相等的意义
  • 提高结构类型的比较速度

 

1)更改相等的意义

当默认的==和Equals不适用(不符合自然规则,或悖离了使用者的期望)于自定义类型时,就需要更改相等的意义。比如DateTimeOffset结构,其有两个私有成员:一个DateTime类型的UTC,以及int类型的offset。如果是你在创建DateTimeOffset类型,那么你很可能只要UTC字段相等即可,而不去比较Offset字段。另外一个例子就是支持NaN的数字类型,比如float和double,如果你来创建这两个类型,你可能会希望NaN也是可以进行比较的。

而对于Class类型,很多时候,使用值比较更有意义。尤其是一些包含较少数据的类,比如System.Uri或System.String

2)提高结构类型的比较速度

结构类型的默认比较算法相对较慢。通过重写Equals方法可以提高5%的性能。而重载==运算和实现IEquatable<T>可以在不装箱操作的情况下实现相等性比较,这使得提高5%性能变得可能。

对于自定义相等比较,有一个特殊的情形,更改结构类型的hashing算法后,hashtable可以获得更好的性能。这是因为hashing算法和相等性比较都发生在栈上。

3)如何重写相等

总地来说,有下面三种方式:

  • 重写GetHashcode()和Equals()
  • 【可选】重载!=和==
  • 【可选】实现IEquatable<T>

I)重写GetHashCode

object对象的虚方法GetHashCode,也就仅仅对于Hashtable类型和Dictionary<TKey,TValue>类型有益。

这两个类型都是哈希表集合,集合中的每个元素都是一个键值用于存储元素和获取元素。哈希表使用了一个特定的策略以有效地基于元素的键值分配元素。这就要求每个键值都有一个Int32数(或哈希码)。哈希码不仅对于每个键值是唯一的,而且还必须有较好的性能。哈希表认为object类定义的GetHashCode方法已经足够了,因此这两个类型都省略了获取哈希码的方法。

无论值类型还是引用类型,都默认实现了GetHashCode方法,所以你不用重写这个方法,除非你需要重写Equals方法。(因此,如果你重写了GetHashCode方法,那么你肯定是需要重写Equals方法)。

是否需要重写GetHashCode方法,可以参考下面的规则:

  • 如果Equals方法返回True是,两个比较的对象必须返回相同的哈希码
  • 不允许抛出异常
  • 除非对象变化了,那么重复的对一个对象调用GetHashCode方法应返回相同的哈希码

为了提高哈希表的性能,GetHashCode需要重写以防止不同的值返回相同的哈希码。也这就说明了为什么需要对结构类型需要重写Equals和GetHashCode方法,因此这样重写比默认的哈希算法更有效率。结构类型的GetHashCode方法的默认实现是在运行时才发生,而且很可能基于结构的每个成员而实现。

// char type
public override int GetHashCode() {
    return (int)m_value | ((int)m_value << 16);
}

// int32
public override int GetHashCode() {
    return m_value;
}

而类(class)类型,GetHashCode方法的默认实现基于内部对象标识,这个标识在CLR中对于每个对象实例都是唯一的。

public virtual int GetHashCode()
{
    return RuntimeHelpers.GetHashCode(this);
}

II)重写Equals

object.Equal的规定(公理)如下:

  • 一个对象不能和null相等(除非对象是nullable类型)
  • 相等性是对称的(一个对象等于自身)
  • 相等性是可交换的(如果a等于b,那么b也等于a)
  • 相等性是可传递的(如果a等于b,b等于c,那么a等于c)
  • 相等性是可重复的,并且是可靠的(不会抛出异常)

III)重载==和!=

除了可重写Equals,还可以重载等于和不等于运算符。

对于结构类型,基本都重载了等于和不等于运算符,如果不重载它们,那么对于结构类型,等于和不等于将返回错误的结果;

而对于类(class)类型,有两种处理方式:

  • 不重载==和!=,因为它们会执行引用相等
  • 重载==和!=,使其与Equals一致

第一种实现适用于大多数自定义类型,特别是可变(mutable)类型。它确保了自定义类型符合==和!=就应该执行引用相等性的比较,从而不会误导这些自定义的使用者。再次回顾一下前面举过的StringBuilder例子

StringBuilder buffer1 = new StringBuilder("123");
StringBuilder buffer2 = new StringBuilder("123");
Console.WriteLine(buffer1 == buffer2); // False, Reference equality
Console.WriteLine(buffer1.Equals(buffer2)); // True, Value equality

而第二种实现适用于使用者永远都不希望自定义类型执行引用相等。一般地这些都类型都是不可变(immutable)类型,比如string类型和System.Uri类型,当然也包含一些引用类型。

III)实现IEquatable<T>

为了保持完整性,建议在重写Equals方法时,同时实现IEquatable<T>接口。接口方法的结果应当与自定义重写后Equals方法的结果一致。如果你已经重写了Equals方法,那么实现IEquatable<T>不需要额外的实现代码(直接调用Equlas方法即可)

internal class Staff : IEquatable<Staff>
{
    public string FirstName { get; set; }

    // implements IEquatable<Staff>
    public bool Equals(Staff other)
    {
        return this.FirstName.Equals(other.FirstName);
    }

    // override Equals
    public override bool Equals(object obj)
    {
        if (obj == null)
            return this == null;

        if (!(obj is Staff))
            return false;

        Staff s = obj as Staff;

        return this.FirstName == s.FirstName;
    }

    // override GetHashCode
    public override int GetHashCode()
    {
        return this.FirstName.GetHashCode();
    }            
}

IV)可插入的相等比较器

如果你希望一个类型在某一个特定的场景下使用不同的比较,那么你可以使用可插件式的IEqualityComparer。它特别适用于集合类。(后续有内容介绍)

 

相等性比较总结

C#类库中,为相等性比较设计了三个接口:IEquatable<T>,IEqualityComparer,以及IEqualityComparer<T>。

IEqualityComparer与IEqualityComparer<T>的差别很简单,一个是非Generic的,需要把T转换成Object,然后调用Object的Equals方法;而后者直接调用T类型实例的Equals方法。

那么IEquatable<T>和IEqualityComparer<T>有什么差别,分别适用于什么场景呢?

1. IEquatable<T>用于比较与自己类型相同的另一个对象是否相等;而IEqualityComparer<T>则用于比较两个相同类型的实例是否相等。

2. 如果两个实例是否相等只有一种可能,或者有几个是否相等的比较但只有其中一个更有意义,那么应该选择IEquatable<T>,T类型自己实现IEquatable<T>接口。因此IEquatable<T>的实例自己就知道该如何比较自己和另外一个实例。与之相反,如果需要比较的实例之间存在多个相等性比较,那么IEqualityComparer<T>更适合这种情况;这个接口不会由T类型实现,相反需要一个外部的类实现IEqualityComparer<T>接口。因为,当比较两个类型实例是否相等时,因为T类型内部不知道如何比较,那么你就需要显示地指定一个IEqualityComparer<T>实例用于执行相等性比较从而满足特定的需求。

3. 例子

internal class Staff : IEquatable<Staff>
        {
            public string FirstName { get; set; }
            public string Title { get; set; }
            public string Dept { get; set; }

            public override string ToString()
            {
                return string.Format(
                    "FirstName:{0}, Title:{1}, Dept:{2}",
                    FirstName, Title, Dept);
            }

            // implements IEquatable<Staff>
            public bool Equals(Staff other)
            {
                return this.FirstName.Equals(other.FirstName);
            }


            // override Object.GetHashCode
            public override int GetHashCode()
            {
                return this.FirstName.GetHashCode();
            }

        }

internal class StaffTitleComparer : IEqualityComparer<Staff>
        {
            public bool Equals(Staff x, Staff y)
            {
                return x.Title == y.Title;
            }

            public int GetHashCode(Staff obj)
            {
                return obj.Title.GetHashCode();
            }

        }

internal class StaffDeptComparer : IEqualityComparer<Staff>
{
    public bool Equals(Staff x, Staff y)
            {
                return x.Dept == y.Dept;
            }

    public int GetHashCode(Staff obj)
    {
        return obj.Dept.GetHashCode();
    }

}


static void Main(string[] args)
        {

            IList<Staff> staffs = new List<Staff> 
            {
                new Staff{FirstName="AAA", Title="Manager", Dept="Sale"},  
                new Staff{FirstName="BBB", Title="Accountant", Dept="Finance"},
                new Staff{FirstName="BBB", Title="Accountant", Dept="Finance"},
                new Staff{FirstName="AAA", Title="Sales", Dept="Sale"},
                new Staff{FirstName="ABA", Title="Manager", Dept="HR"}
            };
            Print("All Staffs", staffs);
            Print("No duplicated first name", staffs.Distinct());
            Print("No duplicated title", staffs.Distinct(new StaffTitleComparer()));
            Print("No duplicated department", staffs.Distinct(new StaffDeptComparer()));

            Console.ReadLine();
        }

private static void Print(string group, IEnumerable<Staff> staffs)
        {
            Console.WriteLine(group);
            foreach (Staff s in staffs)
                Console.WriteLine(s.ToString());

            Console.WriteLine();
        }
Overall

 

--update--

最后一个例子,还可以通过扩展IEnumeable<T>来实现DistinctBy:

public static class IEnurambleExtension
{
    public static IEnumerable<TSource> DistinctBy<TSource, TKey>
        (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    { 
        HashSet<TKey> keys = new HashSet<TKey>();

        foreach (TSource element in source)
            if (keys.Add(keySelector(element))) 
                yield return element;
    }
}

可以这样使用

staffs.DistinctBy(s => s),注意,staff类需要实现IEquatable<T>(或重写Equals和GetHashCode)

staffs.DistinctBy(s => s.Dept),这就省去了编写StaffDeptComparer类

进一步,如果staff的某个字段是一个类,那么这个类同样需要实现IEquatable<T>(或重写Equals和GetHashCode)

 参考资料

1. C# 5.0 in a Nutshell;

2. MSDN, IEquatable<T>, http://msdn.microsoft.com/en-us/library/ms131187.aspx;

3. MSDN IEqualityComparer, http://msdn.microsoft.com/en-us/library/ms132151.aspx;

4. Stackoverflow, http://stackoverflow.com/questions/9316918/what-is-the-difference-between-iequalitycomparert-and-iequatablet

转载于:https://www.cnblogs.com/yang_sy/p/3582946.html

C#元组的相等性比较 元组作为轻量级的数据结构,在c#中具有广泛的引用。但是元组的比较一直以来都是对于成员的依次比较。好在C#7.3开始,引入了元素的相等性比较,让元组的易用性有了大幅提升。 绑定 微软对此的介绍是“从 C# 7.3 开始,元组类型支持 == 和 != 运算符。 这些运算符按顺序将左边参数的每个成员与右边参数的每个成员进行比较,且比较是短路计算” 所以我们可以写出这样的代码,对元组进行比较 var l... 阅读详情

相关推荐

中小公司无线组网实战:用一台H3C AC和普通三层交换,实现办公网AP统一管理

本文详细介绍了中小型企业如何利用H3C AC控制器与普通三层交换机实现无线AP统一管理的实战方案。通过VLAN规划、DHCP配置和AC控制器设置,构建经济高效的办公网络,解决信号覆盖和连接稳定性问题,特别适合50-200人规模的企业部署。

weixin_42531516的博客 382

C#中判断浮点数double/float是否相等

一、float型与零值比较的语句 if(x < -0.000001 && x > 0.000001) // !=0 if(x > -0.000001 && x < 0.000001)// =0 二、float型与float型如何判断相等 浮点数的表示是不精确的,不能直接比较两个数是否完全相等,一般都是在允许的某个范围内认为像个浮点数相等, 如有两个浮点数a,b,允许的误差范围为1e-6,则abs(a-b)<=1e-6,即可认为a和b相等

采菊东篱下,Python满乾坤! 7067

基于CANoe的车载以太网测试

以太网测试 CANoe

Yafet 4554

C#数组比较(IStructuralEquatable接口)

数组和元组都实现了IStructuralEquatable和IStructuralComparable。这两个接口都是.NET4新增的    不仅可以比较引用,还可以比较内容,IStructuralEquatable接口用于比较两个元组或数组是否有相同的内容,    IStructuralComparable接口用于给元组或数组排序    应用范围:可以自定义比较数组中的元素结构是否相同,例

limlimlim的专栏 3417

【电力电子控制】基于强化学习的单相逆变器并网电流控制

本文将尝试以 DQN(Deep Q-Network)为例,设计并训练一个面向单相逆变器的智能控制器,实现对并网电流的精准调节。

weixin_62596197的博客 463

别急着让AI画板!聊聊Cadence Allegro X AI和OrCAD X在实际PCB项目中的真实体验

本文分享了Cadence Allegro X AI与OrCAD X在PCB设计中的实际应用体验,探讨了AI辅助Layout的效率提升与潜在陷阱。通过高速ADC采集板案例,详细对比了AI与传统方法在电源平面分割、低速信号布线等任务中的表现,并总结了人机协作的最佳实践,为工程师提供实用参考。

weixin_30836759的博客 2214

IEqualityComparer<T> VS System.IEquatable<T>

类似于IComparer VS IComparable. public interface ">IComparable<in T> {    // Methods         <a title="System.Int32 CTRL+Click to open in new tab." href="http://127.0.0.1/roeder/dotnet/Default.as

albertliangyg的专栏 1727

1、语义数据建模:避免陷阱与突破困境

本文探讨了语义数据建模的兴起背景、核心概念、生命周期及常见挑战。从数据丰富型组织和AI开发者的需求出发,分析了语义建模的关键元素和质量维度,并深入讨论了建模过程中可能出现的陷阱与解决方案。文章还针对语义模型的演化、治理和战略组织问题提供了突破思路,旨在帮助数据从业者更好地理解和应用语义建模技术,以提升数据驱动应用的有效性。

c8d9e0f1的博客 119

c#中double类型计算比较

c#中double类型计算比较 日常填坑的一天,今天遇到个比较基础的问题,两个double类型的数据相加与第三个double类型数据进行比较判断是否相等。 通过计算器计算明明相等但是代码判断IF就是不相等,查阅资料发现double类型的1.0在计算机中显示为0.9999999999…,所以这有可能是不相等的原因。 之后我就换成decimal类型就行相加比较,然后就ok了。所以在开发中尽量不要用double类型判断比较 ...

Probieone的博客 1726

3dmax文件格式转换——.max 转换为 .flt(解决转换后.flt没有纹理贴图的问题)

本文主要介绍如何在3dmax中将.max格式文件转换为.flt格式文件,并解决转换后的文件没有纹理贴图的问题。 在3dmax中,将.max文件转换为.flt格式,只需导出选择.flt格式即可,但是导出的文件在osgEarth中加载后,缺少纹理和贴图。 下面是解决方案: 1、选中加载的模型,然后点击 渲染-> 渲染到纹理 2、将 渲染到纹理 子窗口往下拉,点击 添加 按钮,添加 ...

cchangcs 6171

C#利用最小二乘法拟合任意次函数曲线

给出一组离散点,确定一个函数逼近原函数,插值是这样的一种手段。在实际中,数据不可避免的会有误差,插值函数会将这些误差也包括在内。因此,我们需要一种新的逼近原函数的手段: ①不要求过所有的点(可以消除误差影响);②尽可能表现数据的趋势,靠近这些点。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小 [1],其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达,具体可以查阅相关资料。最小二乘法(又称最小平方法)是一种数学技术。

qq_30725967的博客 3755

C#深入理解比较对象的相等性

C#比较对象的相等性 1、比较引用类型的相等性 引用类型都继承自object类型,object类型有如下的用来比较对象相等性的方法: 1)static bool ReferenceEquals(Object objA, Object objB) 该方法是一个静态方法,比较的是两个对象的引用,其中null等于null。 2)virtual bool Equals(Object obj); 该方法是一个虚方法,可以在自己的类中重写它,从而按值来比较对象。 3)static bool Equals(Object

目标:MVP 324

二极管钳位电路、限幅电路和检波电路Multisim电路仿真

本文系统介绍了二极管钳位、限幅和检波三种基础电路的工作原理及Multisim仿真验证。钳位电路通过电容-二极管配合实现波形整体平移,将波峰或波谷固定在指定电压;限幅电路利用二极管导通特性削除信号超出设定阈值的部分;检波电路则通过半波整流和电容滤波从调幅波中提取音频信号。三种电路均通过Multisim仿真验证了理论分析结果,展示了二极管在信号处理中的关键作用。这些基础电路广泛应用于信号调理、电平保护和通信解调等领域。

XU157303764的博客 1124

C# 比较对象的相等性

对象相等的机制有所不同,这取决于比较的是引用类型(类的实例)还是值类型(基本数据类型、结构或枚举的实例)。下面分别介绍引用类型和值类型的相等性。01比较引用类型的相等性System.Obj...

zls365365的博客 921

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【转载】C#相等性比较

本文阐述C#中相等性比较,其中主要集中在下面两个方面 ==和!=运算符,什么时候它们可以用于相等性比较,什么时候它们不适用,如果不使用,那么它们的替代方式是什么? 什么时候,需要自定一个类型的相等性比较逻辑 在阐述相等性比较,以及如何自定义相等性比较逻辑之前,我们首先了解一下值类型比较和引用类型比较 值类型比较对比引用类型比较 C#中的相等性比较有两种: 值类型相等,两个值在某种场景下相等 引...

weixin_33893473的博客 159

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C#的相等性比较

Equals() 和运算符 == 的重载准则(C# 编程指南) C# 中有两种不同的相等:引用相等和值相等。值相等是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。引用相等意味着要比较的不是两个对象,而是两个对象引用,这两个对象引用引用的是同一个对象。这可以通过简单的赋值来实现,如下面的示例所示:C# 复制代码

深海狂鲨 916

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C# 实现一个基于值相等性比较的字典

C# 实现一个基于值相等性比较的字典Intro今天在项目里遇到一个需求,大概是这样的我要比较两个 JSON 字符串是不是相等,JSON 字符串其实是一个 Dictionary<st...

dotNET跨平台 406

C#比較对象的相等性

   对于相等的机制全部不同,这取决于比較的是引用类型还是值类型。以下分别介绍引用类型和值类型的相等性。 1.比較引用类型的相等性    System.Object定义了三种不同的方法,来比較对象的相等性:ReferenceEquals()和两个版本号的Equals()。再加上比較运算符(==)。实际上有4种进行比較相等的方式。 1.1 ReferenceEquals...

weixin_33730836的博客 100

【C# ValueTuple 相等性深度解析】:揭秘值元组比较背后的底层机制与性能陷阱

深入解析C# ValueTuple 的相等性比较机制,揭示其基于值的递归比较原理与性能影响。涵盖常见应用场景、Equals方法实现及装箱陷阱,助你写出更高效的元组比较代码。值得收藏

LogicGap的博客 894

C#中匿名类型的相等性比较陷阱(Equals重写机制大揭秘)

揭秘C#匿名类型相等性比较陷阱,深入解析C#匿名类型的Equals重写机制。涵盖编译器自动生成的Equals、GetHashCode实现原理,适用于集合去重、对象比较等场景,确保类型安全与性能兼备。理解底层逻辑,避免常见误区,值得收藏。

ProceChat的博客 582

c#引用相等性比较(ReferenceEquals)

Object.ReferenceEquals方法原型 public static bool ReferenceEquals( object objA, object objB) namespace TestReferenceEquality { struct TestStruct { public int N...

awhpp88888的博客 1027

【ValueTuple 相等性深度解析】:揭秘C#中值元组比较的底层原理与性能优化策略

深入解析ValueTuple相等性判断机制,揭示C#中值元组比较的底层原理与高效实现方式。涵盖结构化相等、编译优化及常见应用场景,提升代码性能与可读性。值得收藏

CompiShoal的博客 452
上一篇: c#列举和迭代器
下一篇: Customer IEnuramble Extension
aoding8407
博客等级 码龄11年 2粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值