1. 程式人生 > >c# 重載運算符(ovveride operator)踩坑記,關於null比對

c# 重載運算符(ovveride operator)踩坑記,關於null比對

漏洞 pre console blog 為什麽 留言 報表 bool 解決辦法

場景描述:

需要比對兩個版本的對應對象是否完全一致(每個屬性值一致),不一致的導出報表顏色標識,以便提醒後續使用報表人員。

實現思路:

對象重載ToString方法,另實現一比對基類(為了通用)重載==與!=運算符,所有比對對象繼承於比對基類。

代碼:

class A:C
    {
        public A(string a, string b)
        {
            AA = a;
            BB = b;
        }
        public string AA { get; set; }

        public string
BB { get; set; } public override string ToString() { return AA+BB; } } class B:C { public B() { } public B(string a, string b) { AA = a; BB = b; } public string AA { get; set; }
public string BB { get; set; } public override string ToString() { return AA + BB; } } class C { public static bool operator ==(C a, C b) { //這裏有漏洞,對象比對,如果是和null比對呢,以下。。。呵呵了 string _a = a.ToString();
string _b = b.ToString(); return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b; } public static bool operator !=(C a, C b) { return true; } } class Test { public void Compare() { Console.WriteLine(new A("a", null) == new A("a", "b"));//正常 Console.WriteLine(new B("a", "b") == new B("a", "b"));//正常 Console.WriteLine(new B("a", "b") == null);//額,這個是直擊漏洞 } }

怎麽解決漏洞呢,第二版C類:

class C
    {
        public static bool operator ==(C a, C b)
        {
            //這裏會死循環System.StackOverflowException異常
            if (a == null || b == null)
            {
                if (a == b)
                    return true;
                return false;
            }
            string _a = a.ToString();
            string _b = b.ToString();
            return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
        }

        public static bool operator !=(C a, C b)
        {
            return true;
        }
    }

為什麽呢?等拋出異常後,明白了,在判斷a==null的時候,不同樣需要執行重載後的==嗎?一遍一遍的執行,死循環唄。

思考一下,有沒有什麽解決辦法?如果當前自己寫的重載有問題,那能不能用沒問題的重載呢?比如所有類的基類object,而object==null是不報異常的,那就考慮第三版,如下:

class C
    {
        public static bool operator ==(C a, C b)
        {
            //借用object==null來判斷,類型轉換,耗時
            if ((a as object) == null)
            {
                return (b as object) == null;
            }
            if ((b as object) == null)
                return false;
            string _a = a.ToString();
            string _b = b.ToString();
            return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
        }

        public static bool operator !=(C a, C b)
        {
            return true;
        }
    }

我本人不通底層的東西,但是,類型轉換確實耗時,我這邊報表是幾萬條數據的比對,當然,我也沒測,於是想到一重可以通過is判斷類型的思路,如下:

class C
    {
        public static bool operator ==(C a, C b)
        {
            //借用is判斷類型
            if ((a is C) && (b is C))
            {
                string _a = a.ToString();
                string _b = b.ToString();
                return _a.Length == _b.Length && _a.GetHashCode() == _b.GetHashCode() && _a == _b;
            }
            return !(a is C) && !(b is C);
        }

        public static bool operator !=(C a, C b)
        {
            return true;
        }
    }

以上是我的思路,如果哪位大神懂為什麽object==null比對是沒問題的,還請告知,再次謝過,歡迎大家留言。

c# 重載運算符(ovveride operator)踩坑記,關於null比對