2012-03-28 59 views
1

我正在尋找一種方法來解釋通過調用ReferenceEquals()來拋出高級業務邏輯是不合理的。比較線程的相等性

下面是一個代碼片段,我有一個問題(在方法,設計前提拋出,如果我們是在一個錯誤的線程):

if (!object.ReferenceEquals(Thread.CurrentThread, RequestHandlerThread)) 

它是可靠的,而不是寫:

if (Thread.CurrentThread != RequestHandlerThread) 

我建議在比較中使用ManagedThreadIds,基於我在教程中常見的內容。對手說,參照平等的比較似乎更加面向對象。

這裏(大致)是我在.NET 4.0的System.Object的Reflector視圖中看到的。請記住,Thread類是密封的,並且對於operator ==沒有重載。

public static bool ReferenceEquals(object objA, object objB) 
{ 
    return (objA == objB); 
} 

public static bool Equals(object objA, object objB) 
{ 
    return (objA == objB || 
     (objA != null && objB != null && objA.Equals(objB))); 
} 

這是一些基本的測試,驗證線程池上的操作......我錯過了任何重要的測試嗎?

using System.Threading; 
using System.Diagnostics; 
using System.Threading.Tasks; 

namespace ConsoleApplicationX 
{ 
    class Program 
    { 
     static readonly Thread mainThread; 

     static Program() 
     { 
     mainThread = Thread.CurrentThread; 
     } 

     static void Main(string[] args) 
     { 
     Thread thread = Thread.CurrentThread; 
     if (thread != Thread.CurrentThread) 
      Debug.Fail(""); 

     if(Thread.CurrentThread != thread) 
      Debug.Fail(""); 

     if (thread != mainThread) 
      Debug.Fail(""); 

     var task = Task.Factory.StartNew(() => RunOnBackground(thread)); 
     task.Wait(); 

     var anotherThread = new Thread(new ParameterizedThreadStart(RunInAnotherThread)); 
     anotherThread.Start(thread); 
     } 

     static void RunOnBackground(Thread fromInitial) 
     { 
     if (Thread.CurrentThread == fromInitial) 
      Debug.Fail(""); 

     if (fromInitial != mainThread) 
      Debug.Fail(""); 
     } 

     static void RunInAnotherThread(object fromInitialAsObject) 
     { 
     var fromInitial = (Thread)fromInitialAsObject; 

     if (Thread.CurrentThread == fromInitial) 
      Debug.Fail(""); 

     if (fromInitial != mainThread) 
      Debug.Fail(""); 
     } 
    } 
} 
+1

FWIW,我個人從未見過System.Object.ReferenceEquals在「operator ==」的實現之外的任何地方使用。 – 2012-03-28 17:30:22

+0

在Equals()'實現中使用的ReferenceEquals() – sll 2012-03-28 20:17:57

回答

0

簡短回答:

使用ManagedThreadId屬性進行比較。

簡單的例子:

假設我們有一個名爲StackOverflow.MessageThread類。程序員胖手指一個函數的前提條件,說Debug.Assert(Thread.CurrentThread == messageThread)。前提條件在運行時失敗。如果開發人員將達到ManagedThreadId,他會在編輯時發現這是不可能的,並且會在開發週期的早期解決問題。

2

你是對的。正如你的反映查詢所示,這兩種方式是等價的(除了以對手方式進行額外的方法調用)

6

試圖不鼓吹,但是... 一般來說,如果有一個身份屬性要使用, case

Thread.ManagedThreadId 

它應該用於相等比較,除非執行代碼存在性能約束。指針比較的語義與平等很不相同。另外,指針比較依賴於mscorlib中Thread的實現。

+0

歡迎並感謝KeithP的有趣解答。 – 2012-03-28 21:54:30

1

我可以看到一個實現如何使用兩個不同的引用,但仍然指向內部的同一個線程。假設參考平等意味着威脅是平等的,這很好。但是,這並不意味着如果它們不同於對象在語義上不相等。僅此一點就足以反對在業務邏輯中比較參考的做法。

+0

不,因爲目前引用** do **很可能指向同一個實例。然而,這並不是對未來的保證。一個通用的答案有點太簡單了,你可以創建一個數字的兩個實例並對它們進行比較,即使它們是相等的,也可以看到它們在參考時失敗(呃,呃!)。 – 2012-03-29 13:32:34