2009-01-22 62 views
3

我有一個具有enum屬性和布爾屬性的類,它基於它調用具體參數的特定方法。我在開關的每種情況下使用enum的switch語句和if作爲布爾值。這是一個很長的名單,並不覺得我是最優雅的解決方案。任何人都有更優雅或更簡單的方式來實現這一點?C#枚舉和布爾 - 尋找更優雅的方式

  switch (ReadDecision) 
      { 
       case ReadDecisions.ReadNext: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.Receive(Timeout); 
         } 
         else 
         { 
          Message = queue.Receive(); 
         } 
         break; 
        } 
       case ReadDecisions.PeekNext: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.Peek(Timeout); 
         } 
         else 
         { 
          Message = queue.Peek(); 
         } 
         break; 
        } 
       case ReadDecisions.ReadMessageId: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.ReceiveById(Id, Timeout); 
         } 
         else 
         { 
          Message = queue.ReceiveById(Id); 
         } 
         break; 
        } 
       case ReadDecisions.PeekMessageId: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.PeekById(Id, Timeout); 
         } 
         else 
         { 
          Message = queue.PeekById(Id); 
         } 
         break; 
        } 
       case ReadDecisions.ReadCorrelationId: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.ReceiveByCorrelationId(Id, Timeout); 
         } 
         else 
         { 
          Message = queue.ReceiveByCorrelationId(Id); 
         } 
         break; 
        } 
       case ReadDecisions.PeekCorrelationId: 
        { 
         if (UseTimeout) 
         { 
          Message = queue.PeekByCorrelationId(Id, Timeout); 
         } 
         else 
         { 
          Message = queue.PeekByCorrelationId(Id); 
         } 
         break; 
        } 
       default: 
        { 
         throw new Exception("Unknown ReadDecisions provided"); 
        } 
      } 

回答

3

一個常用的約定是零超時意味着沒有超時。也許你可以放棄UseTimeout(property?)並使用零值。這會消除一些東西。

3
+0

有很多情況下,簡單的枚舉正是你所需要的。當你開始注意代碼中enum上的許多switch語句的代碼味道時,你開始需要用類替換它們。 – 2009-01-22 11:08:45

+0

是的,你完全正確 - 用六個類取代枚舉就是爲了消除這個switch語句會過度。 – gkrogers 2009-01-22 11:47:32

5

根據什麼queue是,你可以改變Peek()Peek(bool)Peek(bool?)的簽名? (中其餘的方法應遵循爲好。)

這樣,而不是:

if (UseTimeout) 
{ 
    Message = queue.Peek(Timeout); 
} 
else 
{ 
    Message = queue.Peek(); 
} 

你可以有:

Message = queue.Peek(UseTimeout ? Timeout : null); 

另一個想法是,你可以推動決策結構到隊列類:

if(UseTimeout) 
    Message = queue.PerformAction(ReadDecision, Timeout) 
else 
    Message = queue.PerformAction(ReadDecision) 
3

我在這裏看到的模式是很多名爲foo(ID)的方法對和foo(ID,超時)。在你情我願:

  • 創建第三種方法foo(ID, timeout, bool useTimeout)的,通過合併foo(ID)foo(ID, timeout)屍體。
  • 變化foo(ID)調用foo(ID, null, false)foo(ID, timeout)調用foo(ID, timeout, true)
  • 更改switch語句來始終調用foo(ID, Timeout, UseTimeout)
  • 對每個適用的方法對重複上述操作。

通過這樣做,您已經將控制超時使用的標誌移到了更接近實際需要使用的位置。

-1

你對我看起來很好。閱讀是可以理解的,我有信心保持它。沒有必要對它進行幻想 - 莽撞。

例如,使用其他人建議的關於使用類而不是您的枚舉的花式模式可能會導致每個case語句都有一個新類,並且它們可能每個都會進入一個文件,需要另一個基礎接口的文件...這將是一個很多東西的駭人聽聞。我不知道任何人都可以證明這是一個更簡單的方式來表達你已經完成的很好的工作。

+0

爲什麼downvote!是否因爲這不符合你在課本中閱讀的內容? – 2009-01-22 10:42:11

1

我會使用含有枚舉作爲重點和措施,你做一個值的字典:

Dictionary<ReadDecisions,YourAction> decisions = new 
      Dictionary<ReadDecisions,YourAction>(); 

decisions[ReadDecisions.ReadNext] = queue.Receive; 
decisions[ReadDecisions.PeekNext] = queue.PeekById; 
// you understand the main idea 
//.... 

然後用替換交換機:

if(UseTimeout) 
    decisions[ReadDecision](id, Timeout); 
else 
    decisions[ReadDecision](id, 0); //or another value 
            //telling you there is no timeout . 
            // it just have to be the same signature 

唯一的問題是,你必須具有相同簽名的所有方法。

0

您可以使用代表散列表,其中的關鍵將是ReadDecision和UseTimeout的組合嗎?
我有一種感覺在問了這裏downvote ...

0

爲什麼不簡化您的隊列方法通過

int? optionalTimeout = UseTimeout ? Timeout : null; 

switch (ReadDecision) { 
    case ReadDecisions.ReadNext: 
     Message = queue.Receive(optionalTimeout); break; 

    case ReadDecisions.PeekNext: 
     Message = queue.Peek(optionalTimeout); break; 

    // and so on ... 

然後參數處理被傳爲Timeout爲空值「不超時「

2

我喜歡斯科特的建議有一個零超時意味着沒有超時。這將導致下面的代碼更具可讀性,但不涉及創建任何額外的類。 OTOH,如果你在代碼中的其他地方有這個相同的switch語句,我會去enum-> class重構。

switch (ReadDecision) 
{ 
    case ReadDecisions.ReadNext: 
    { 
    Message = queue.Receive(Timeout); 
    break; 
    } 
    case ReadDecisions.PeekNext: 
    { 
    Message = queue.Peek(Timeout); 
    break; 
    } 
    case ReadDecisions.ReadMessageId: 
    { 
    Message = queue.ReceiveById(Id, Timeout); 
    break; 
    } 
    case ReadDecisions.PeekMessageId: 
    { 
    Message = queue.PeekById(Id, Timeout); 
    break; 
    } 
    case ReadDecisions.ReadCorrelationId: 
    { 
    Message = queue.ReceiveByCorrelationId(Id, Timeout); 
    break; 
    } 
    case ReadDecisions.PeekCorrelationId: 
    { 
    Message = queue.PeekByCorrelationId(Id, Timeout); 
    break; 
    } 
    default: 
    { 
    throw new Exception("Unknown ReadDecisions provided"); 
    } 
    } 
0

我可以建議如下:

1]「對」方法可以被分組在一起

每個單獨的應該能夠處理NULL值。所以,你將有以下兩類:

Queue.Peek(TimeOut) 
Queue.Receive(TimeOut) 

Queue.ReceiveById(Id, TimeOut) 
Queue.PeekById(Id, TimeOut) 
... 

2]聲明兩位代表的法團

delegate Message MethodType1(Timeout) 
delegate Message MethodType2(Id, TimeOut) 

3]有將返回適當的方法到GetDelegate()方法執行

object GetDelegate(ReadDecisions param) 
{ 
switch(param) 
{ 

    case ReadNext: 
      MethodType1 receiveDlgt = new MethodType1(queue.Receive); 
    case PeekMessageId: 
      MethodType2 peekDlgt = new MethodType2(queue.Peek); 
    ... 
} 
} 

4]進行適當的根據代表類型呼叫

InvokingMethod() 
{ 
    object methodToExecute = GetDelegate(ReadDecision) 
    if (methodToExecute.GetType() == typeof(MethodType1)) 
    { 
    methodToExecute(TimeOut) 
    } 
    else 
    { 
    methodToExecute(Id, TimeOut) 
    } 

} 

希望這會有所幫助。 根據良好的編程習慣,某些部件可能需要改進。

0

你可能不想像你在做的那樣讀q。也許重構的東西使用回調? MessageQueue隊列=新MessageQueue(queuePath); //事件處理程序 queue.ReceiveCompleted + = QueueMessageReceived; //被調用的方法的名稱 //開始「偵聽」消息 queue.BeginReceive();