DotNet_运算符重载,引用,比较

抛出问题:

  1 程序员A在某天Debug代码的时候发现了一个不可思议的问题:从服务端获取两次数据组装的对象 DataObj1,DataObj2,竟然出现 DataObj1 == DataObj2 返回true的情况,两个不同的实例,引用自然而然是不同的,为什么?

  2 程序员B看到C#的Object中定义了一个 public staticbool ReferenceEquals(object objA, object objB) 静态方法,这个是不是多余的?如果Object A,B,我要比较引用不是很直接吗? A == B

解答时间

  代码:Object a, b;

    这里的a和b确实是对Object对象的引用,这一点是没有任何异议的

  但是

  a == b;

的具体含义不能绝对认为这个就是针对 a 和 b的引用比较,因为DotNet/C#支持操作符的重载,关键字是 operator

  a == b 的具体含义依赖于 == 这个操作符的实现:

    1)对于引用类型这个操作符的默认行为是 比较对象的引用

    2)对于值类型这个操作符的默认行为是按照值进行比较

  另外,在重载 == 或者 != 操作符一定需要明确的是一定需要一起重载,成对出现。

  了解了上面的点,上面的问题就很好解决了:

  1)相同类型的不同实例,其引用一定不同,但是使用 == 返回true,很显然,该类型重载了 == 和 !=,这个很好验证可以检查类型的实现即可。

  2)当我们确实希望按照引用进行比较,那么调用 ReferrecneEquals 一定保证比较的实现是基于引用的,这样一来就看出这个方法的独特用处了。

  后面附一个简单的重载实例:

  

using System;
using System.Collections.Generic;
using System.Linq;

namespace EqualImplement
{
    class SampleObject
    {
        private Int32 m_Age;
        private Int32 m_Count;

        public SampleObject(
            Int32 i_age,
            Int32 i_count
            )
        {
            m_Age = i_age;
            m_Count = i_count;
        }

        private static bool IsNull(
            Object i_so
            )
        {
            return ReferenceEquals(i_so, null);
        }

        public override bool Equals(
            Object i_obj
            )
        {
            if (!IsNull(i_obj))
            {
                return base.Equals(i_obj);
            }

            return Equals(i_obj as SampleObject);
        }

        private bool Equals(
            SampleObject i_obj
            )
        {
            return (i_obj.Age == m_Age) && (i_obj.Count == m_Count);
        }

        public Int32 Age
        {
            get
            {
                return m_Age;
            }
        }

        public Int32 Count
        {
            get
            {
                return m_Count;
            }
        }

        public override int GetHashCode()
        {
            return m_Age.GetHashCode();
        }

        public static bool operator ==(
            SampleObject i_so1,
            SampleObject i_so2
            )
        {
            if (!IsNull(i_so1))
            {
                return i_so1.Equals(i_so2);
            }

            if (!IsNull(i_so2))
            {
                return i_so2.Equals(i_so1);
            }

            return true;
        }

        public static bool operator !=(
            SampleObject i_so1,
            SampleObject i_so2
            )
        {
            if (!IsNull(i_so1))
            {
                return (!i_so1.Equals(i_so2));
            }

            if (!IsNull(i_so2))
            {
                return (!i_so2.Equals(i_so1));
            }

            return false;
        }
    }
}

  调用:

 

using System;
using System.Collections.Generic;
using System.Linq;

namespace EqualImplement
{
    class Program
    {
        static void Main(string[] args)
        {
            var so1 = new SampleObject(12, 14);
            var so2 = new SampleObject(12, 14);

            Console.WriteLine("so1 == so2 ?" + ((so1 == so2) ? "Y" : "N"));
            Console.WriteLine("so1 and so2 have the same referrence ? " + ReferenceEquals(so1, so2));

            Console.ReadKey();
        }
    }
}

  输出结果类似:

  so1 == so2 ?Y
  so1 and so2 have the same referrence ? False

  

  

    

  

时间: 2024-11-12 08:03:37

DotNet_运算符重载,引用,比较的相关文章

运算符重载

关键字:operator 相见:<高质量程序设计指南> P255 如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符. 如果运算符被重载为类的成员函数,那么一元运算符没有参数(但是++和--运算符的后置版本除外),二元运算符只有右侧参数,因为对象自己成了左侧参数. 运算符重载的特殊性 如果重载为成员函数,则this对象发起对它的调用 如果重载为全局函数,则第一个参数发起对它的调用 禁止用户发明该语言运算符集合中不存在的运算符 除了函数调用运算符

C++运算符重载的妙用

运算符重载(Operator overloading)是C++重要特性之中的一个,本文通过列举标准库中的运算符重载实例,展示运算符重载在C++里的妙用.详细包含重载operator<<,operator>>支持cin,cout输入输出.重载operator[],实现下标运算.重载operator+=实现元素追加:重载operator()实现函数调用.假设你对C++的运算符重载掌握的游刃有余.那就无需继续往下看了. 运算符重载带来的优点就是--让代码变得简洁.以下将展示几个标准库因使

网易云课堂_C++开发入门到精通_章节4:运算符重载

课时23运算符重载 运算符重载 重载赋值运算符 Person& Person::operator=(const Person& other) { //检查自赋值 if (this == &other) { return *this; } //释放原有的内存资源 delete[]m_data; int length = strlen(other.m_data); m_data = new char[length + 1]; strcpy(m_data, other.m_data);

关于c++的运算符重载那些事

搞c++有一段时间了,今天突然要重载一个运算符,发现自己有点忘了,遂查查资料做一下c++运算符重载的小总结. 一.何为运算符重载 运算符的重载是c++语言特有的,java什么的是没有运算符重载的,所以运算符重载在笔试面试中有可能成为c++的高频考点.运算符重载就是重新定义运算符的意义,如常用的+,-,×,÷都是可以重载的.运算符重载使用的是关键字operator,表现形式是:                                                            

C++:运算符重载函数之&quot;++&quot;、&quot;--&quot;、&quot;[ ]&quot;的应用

5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++(X &ob) //友元函数重载,其中ob为类X的对象的引用 对于后缀方式++ob,可以用运算符函数重载为: ob.operator++(int) //成员函数重载 或 operator++(X &ob,int) //友元函数重载,其中ob为类X的对象的引用 调用时,参数int一般被传递给值0

C++哪些运算符重载可以重载?

运算符重载是C++极为重要的语言特性之一,本文将用代码实例回答--C++哪些运算符可以重载?如何重载?实现运算符重载时需要注意哪些? 哪些运算符可以重载,哪些不可重载? C++98,C++0x,C++11对"哪些运算符重载可以重载"有一致的规定,具体如下: 其中,很少使用的是","(逗号运算符). 标准同样规定了不可重载的运算符: 其中,"::"是作用域运算符, "?:"是条件运算符. 两个较少使用的运算符是 .* 和 -&g

C++ Primer笔记12_运算符重载_递增递减运算符_成员访问运算符

1.递增递减运算符 C++语言并不要求递增递减运算符必须是类的成员.但是因为他们改变的正好是所操作对象的状态,所以建议设定为成员函数. 对于递增与递减运算符来说,有前置与后置两个版本,因此,我们应该为类定义两个版本的递增与递减运算符. 问题来了,程序是如何区分前置和后置呢?因为都是++和-- 为了解决这个问题,后置版本的递增递减运算符接受一个额外的(不被使用)int类型的形参.当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参.这个形参唯一的作用就是区分前置和后置运算符函数. 因为不会

C++:运算符重载函数之友元运算符重载

5.2.2 友元运算符重载函数 运算符重载函数一般采用两种形式定义: 一是定义为它将要操作的类的成员函数(简称运算符重载函数): 二是定义为类的友元函数(简称为友元运算符重载函数). 1.定义友元运算符重载函数的语法如下: 在类的内部: friend 函数类型 operator运算符(形参表) { 函数体 } 在类的内部声明,在类外定义: class X{ ... friend 函数类型 operator运算符(形参表): }; 函数类型 X::operator运算符(形参表) { 函数体 }

C++之------运算符重载

①  什么是运算符重载? 何为C++的运算符重载呢? 其实就是运算符给它重新赋予新的含义或者多重含义.让它有另外一种新的功能. 为什么需要运算符重载? 面向对象中为了实现类的多态性,我们就引用了运算符重载 程序中可以利用“+”.“—” 对整数.单精度.双精度以及指针进行加法和减法运算等 例如: 1 int a = 1+2; //对整数加 2 double d = 1.0+2.54; //对双精度加 3 int por[10]; 4 int *p = por; 5 p = p- 1; //对指针减