C#enums和booleans - 寻找更优雅的方式

时间:2009-01-22 09:44:15

标签: c# enums

我有一个具有枚举属性和布尔属性的类,基于它调用具有特定参数的特定方法。我对enum使用switch语句,在switch的每种情况下使用if作为布尔值。这是一个很长的清单,并不觉得我是最优雅的解决方案。任何人都有更优雅或更简单的方法来实现它?

            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");
                    }
            }

11 个答案:

答案 0 :(得分: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)

答案 1 :(得分:3)

答案 2 :(得分:3)

我在这里看到的模式是很多名为foo(ID)和foo(ID,timeout)的方法对。在你的情况下,我会:

  • 通过合并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)
  • 对每对适用的方法重复上述步骤。

通过执行此操作,您已将控制超时使用的标志移动到更接近实际需要使用的位置。

答案 3 :(得分:3)

常用的约定是超时为零意味着没有超时。也许您可以删除UseTimeout(属性?)并使用值零。那会消除一些东西。

答案 4 :(得分:2)

我喜欢Scott建议零暂停意味着没有超时。这将导致以下代码更易读,但不涉及创建任何额外的类。 OTOH,如果你在代码中的任何其他位置都有相同的switch语句,我会去enum->类重构。

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");
   }
  }

答案 5 :(得分: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

唯一的问题是你必须拥有相同签名的所有方法。

答案 6 :(得分:0)

你能否使用一个代表哈希表,其中键是ReadDecision和UseTimeout的组合?
我有一种感觉'在这里要求一个downvote ...

答案 7 :(得分: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传递的空值为“不要超时”

答案 8 :(得分: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)
    }

}

希望这会有所帮助。 根据良好的编程习惯,某些部分可能需要改进。

答案 9 :(得分:0)

你可能不想像你一样阅读q。也许重构使用回调的东西? MessageQueue queue = new MessageQueue(queuePath); //事件处理程序 queue.ReceiveCompleted + = QueueMessageReceived; //被调用的方法的名称 //开始“收听”消息  queue.BeginReceive();

答案 10 :(得分:-1)

你所拥有的对我来说很好看。阅读是可以理解的,我有信心保持它。没有必要对它嗤之以鼻。

例如,使用其他人建议的关于使用类而不是枚举的花式模式可能会为每个case语句生成一个新类,并且它们可能每个都进入一个文件,你需要基本接口的另一个文件......这将是很多东西。我不知道有多少人可以证明这很多东西是为了表达你已经做得很好的一种简单方法。