首頁 後端開發 C#.Net教程 C#基礎知識整理:基礎知識(12) 超類別Object

C#基礎知識整理:基礎知識(12) 超類別Object

Feb 11, 2017 pm 01:28 PM

    物件導向三大功能:封裝,繼承,多態。那麼類別是從哪裡繼承呢?在物件導向語言中有基底類別或也叫做超類別的概念,也就是所有類別都是從這個類別繼承得來的,這個超類別叫Object。 .net中是這樣描述Object類別的:
    支援 .NET Framework 類別層次結構中的所有類別,並為衍生類別提供低階服務。這是 .NET Framework 中所有類別的最終基底類別;它是類型層次結構的根。
既然是超類,Object定義了一些關鍵的方法。如下:

Equals方法-用於比較兩個實例是否相等。
public virtual bool Equals(Object obj),比較目前實例是否與obj相等;
public static bool Equals(Object objA,Object objB),比較指定兩個實例是否相等。

Finalize 方法——允許 Object 在「垃圾回收」回收 Object 之前嘗試釋放資源並執行其他清理操作。

GetHashCode 方法-取得一個物件的Hash值。

GetType方法-取得目前實例的Type。

MemberwiseClone 方法-建立目前實例的淺表副本,也就是如果目前實例有值,新建立的實例只取得值類型的值,引用型別是沒有取得值。

ReferenceEquals 方法-比較兩個實例是否相同,與static bool Equals(Object objA,Object objB)用法一樣。

ToString 方法-這個平常用的比較多,用來傳回目前實例的string。
Object是超類,所以C#中的所有類別都有這些方法。

下面著重介紹下Equals和ToString方法。
一、物件比較
C#中有值型別與參考型,簡單的理解就是值型別保存物件的值,而引用型別是實例的引用,類似C語言的指標。因此在使用物件的比較的時候,值類型比較兩個物件值是否相等,引用類型比較指定的參考是否引用同一個物件。當然有時也會比較引用型別指向的實例值是否相同。
下面是物件比較的程式碼:

using System;
using System.Collections.Generic;
using System.Text;

namespace YYS.CSharpStudy.MainConsole.AboutObject
{
    public class Int32Value : ICloneable
    {
        //字段,定义字段最好赋上初值
        private int intValue = 0;

        /// <summary>
        /// 属性
        /// </summary>
        public int IntValue
        {
            get
            {
                return this.intValue;
            }

            set
            {
                this.intValue = value;
            }
        }

        /// <summary>
        /// 定义一个无参构造器
        /// </summary>
        public Int32Value() { }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        public Int32Value(int value)
        {
            this.intValue = value;
        }

        ///// <summary>
        ///// 实现ICloneable接口
        ///// </summary>
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
}
登入後複製

呼叫:

using System;
using YYS.CSharpStudy.MainConsole.AboutObject;

namespace YYS.CSharpStudy.MainConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明一个Int32Value类型的引用value1,指向一个实例
            Int32Value value1 = new Int32Value(30);

            //声明value2,指向value1,此时两个引用是指向一个实例的
            Int32Value value2 = value1;

            //使用==比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//相同

            //调用Clone,复制一个value1的副本,赋值给value2
            //此时是两个实例了
            value2 = (Int32Value)value1.Clone();

            //使用==比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//不相同

            //将value1赋给value2,此时他们指向同一个实例
            value2 = value1;

            //使用Equals比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同

            //调用Clone,复制一个value1的副本,赋值给value2
            //此时是两个实例了
            value2 = (Int32Value)value1.Clone();

            //使用Equals比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//不相同

            Console.ReadLine();
        }
    }
}
登入後複製

結果:

由程式碼可以看出:

a、對於引用型,=運算子將參考從一個變數傳遞到另一個變數,所以=兩邊的變數引用同一個物件;
 
b、對於引用相同的兩個變量,使用==運算子傳回true;

c、物件的Clone方法產生一個新實例,傳回該實例的引用,該實例的所有欄位值和原物件相同,即Clone方法得到物件的副本。從Object類別繼承下來的保護方法MemberwiseClone傳回目前物件的副本;

d、對於Clone方法傳回的對象,其參考和原物件不同,==運算子回傳false;

e、從Object繼承下來的Equals方法結果和==運算子相同,只是比較目前引用(this)和參數保存的參考是否引用到了同一個物件上。
在上述程式碼的基礎上,重寫Equals方法。

using System;
using System.Collections.Generic;
using System.Text;

namespace YYS.CSharpStudy.MainConsole.AboutObject
{
    public class Int32Value : ICloneable
    {
        //字段,定义字段最好赋上初值
        private int intValue = 0;

        /// <summary>
        /// 属性
        /// </summary>
        public int IntValue
        {
            get
            {
                return this.intValue;
            }

            set
            {
                this.intValue = value;
            }
        }

        /// <summary>
        /// 定义一个无参构造器
        /// </summary>
        public Int32Value() { }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        public Int32Value(int value)
        {
            this.intValue = value;
        }

        ///// <summary>
        ///// 实现ICloneable接口
        ///// </summary>
        public object Clone()
        {
            return this.MemberwiseClone();
        }

        /// <summary>
        /// 覆盖Equals方法
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            bool isEquals = Object.ReferenceEquals(obj, this);

            if (isEquals == false)
            {
                Int32Value value = obj as Int32Value;

                if (value != null)
                {
                    isEquals = value.intValue == this.intValue;
                }
            }
            return isEquals;
        }
    }
}
登入後複製

呼叫

using System;
using YYS.CSharpStudy.MainConsole.AboutObject;

namespace YYS.CSharpStudy.MainConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明一个Int32Value类型的引用value1,指向一个实例
            Int32Value value1 = new Int32Value(30);

            //声明value2,指向value1,此时两个引用是指向一个实例的
            Int32Value value2 = value1;

            //使用==比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//相同

            //调用Clone,复制一个value1的副本,赋值给value2
            //此时是两个实例了
            value2 = (Int32Value)value1.Clone();

            //使用==比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1 == value2 ? "相同" : "不相同"));//不相同

            //将value1赋给value2,此时他们指向同一个实例
            value2 = value1;

            //使用Equals比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同

            //调用Clone,复制一个value1的副本,赋值给value2
            //此时是两个实例了
            value2 = (Int32Value)value1.Clone();

            //使用Equals比较
            Console.WriteLine(string.Format("value1和value2 {0}", value1.Equals(value2) ? "相同" : "不相同"));//相同

            Console.ReadLine();
        }
    }
}
登入後複製

結果:

修改後的程式碼:
覆寫了Equals方法,程式運作結果則不同了:Equals不再比較兩個變數所保存的物件參考是否相同,而是比較兩個變數所引用的物件是否具有相同的屬性值。
覆蓋後的Equals執行流程是這樣的:
我們看一下覆蓋後Equals方法的具體執行流程:

a、使用Object靜態方法ReferenceEquals比較參數obj和當前物件引用(this)是否相同,如果引用相同,則必為相同物件;
b、如果變數obj和目前引用不相同,則使用as運算符,嘗試將obj類型轉換和目前物件相同的類型,轉換成功表示obj變數引用著和目前物件類別相同的對象,as運算子轉換後物件的引用,否則返回null,只有同類型的物件才需要比較,不同類型的物件必然是不同的物件;
c、如果as運算子轉換物件成功,則進一步比較目前物件引用(this)和參數obj引用物件的欄位值是否相等。
由上面兩段程式碼可以看出:
==和Object類別的Equals方法都是比較對象的引用是否相同,並不比較對象的字段是否相等;而Equals方法可以覆蓋,以求讓其對對象的字段進行等值比較或其它的比較的需求。
因此,如果需要比較兩個C#引用類型變量,除非確定需要比較的就是物件參考時才可以使用==運算符,否則應該使用物件的Equals方法,防止物件所屬的類別覆寫了這個方法。

上面是引用类型的比较,相对来说,值类型的比较就比较纯粹。值类型是不存在引用的,所以值类型就是比较两个对象值是否相等。当然如果覆盖了Equals方法就除外了。不过一般情况下,我们无需覆盖Equals方法。对于引用类型来说,等值比较就是比较对象的引用,引用不同的两个对象应该就是不同的对象;对于值类型来说,比较的就是所有字段的值,字段值不同的两个对象是不同的对象。只有在特殊情况下,才需要覆盖Equals方法,已定义某个类特殊的对象比较方法。
对于覆盖Equals方法,要注意:
注意:理论上可以用任意代码覆盖Equals方法,但要保证如下原则:
a、Equals只能用于对象比较,不能做其它任何用途;
b、对于两个已存在的对象,在对象未作任何改变的情况下,无论任何时候调用Equals方法,返回的结果应该是一样的;
c、对于对象a和b,则a.Equalse(b)和b.Equals(a)返回的结果应该是一样的;
d、覆盖了Equals方法,同时要覆盖GetHashCode(方法),这个后面再详细说明。

二、ToString()
代码:

   public class Int32Value : ICloneable
    {
        //字段,定义字段最好赋上初值
        private int intValue = 0;

        /// <summary>
        /// 属性
        /// </summary>
        public int IntValue
        {
            get
            {
                return this.intValue;
            }

            set
            {
                this.intValue = value;
            }
        }

        /// <summary>
        /// 定义一个无参构造器
        /// </summary>
        public Int32Value() { }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        public Int32Value(int value)
        {
            this.intValue = value;
        }

        ///// <summary>
        ///// 实现ICloneable接口
        ///// </summary>
        public object Clone()
        {
            return this.MemberwiseClone();
        }

     
        /// <summary>
        /// 重写ToString方法
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.intValue.ToString();

            //return "重写ToString";
        }
    }
登入後複製

调用:

     class Program
    {
        static void Main(string[] args)
        {
            Int32Value value = new Int32Value(30);

            Console.WriteLine(value.ToString());//30

            //Console.WriteLine(value.ToString());//重写ToString

            Console.ReadLine();
        }
    }
登入後複製

可以看出,ToString方法可以用任意代码覆盖,只要返回string即可,但是在覆盖时也要返回符合需求的返回值。

以上就是C#基础知识整理:基础知识(12) 超类Object 的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1249
24
使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

xml怎麼改格式 xml怎麼改格式 Apr 03, 2025 am 08:42 AM

可以採用多種方法修改 XML 格式:使用文本編輯器(如 Notepad )進行手工編輯;使用在線或桌面 XML 格式化工具(如 XMLbeautifier)進行自動格式化;使用 XML 轉換工具(如 XSLT)定義轉換規則;或者使用編程語言(如 Python)進行解析和操作。修改時需謹慎,並備份原始文件。

See all articles