C# 比使用多个if语句检查字典中的键更有效的替代方法

C# 比使用多个if语句检查字典中的键更有效的替代方法,c#,if-statement,C#,If Statement,我有大约45条if语句检查字典是否有那个键 private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID) { MessageName msgName = null; List<MessageName>

我有大约45条if语句检查字典是否有那个键

    private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID)
    {
            MessageName msgName = null;
            List<MessageName> msgNameList = new List<MessageName>();
            var msgObjOuter = new MessageName();

            if (infoHash.ContainsKey("redis_version"))
            {
                msgName = new MessageName();
                msgName.MessageID = msgDescritionAndID["redis_version"];
                msgName.DiagnosticCnt = 0;
                msgName.DiagnosticStr = infoHash["redis_version"]; 
                msgNameList.Add(msgName);
            }
           if (infoHash.ContainsKey("uptime_in_seconds"))
           {
            msgName = new MessageName();
            msgName.MessageID = msgDescritionAndID["uptime_in_seconds"];
            msgName.DiagnosticCnt = Convert.ToInt32(infoHash["uptime_in_seconds"]);
            msgName.DiagnosticStr = "";
            msgNameList.Add(msgName);
          }
          //... 40 more if statements
         return msgNameList;
   }
private List createMsgObject(字典infoHash、字典msgDescritionAndID)
{
MessageName msgName=null;
List msgNameList=新列表();
var msgObjOuter=新消息名();
if(infoHash.ContainsKey(“redis_版本”))
{
msgName=newmessagename();
msgName.MessageID=msgDescritionAndID[“redis_版本”];
msgName.DiagnosticCnt=0;
msgName.DiagnosticStr=infoHash[“redis_版本”];
msgNameList.Add(msgName);
}
if(infoHash.ContainsKey(“正常运行时间(秒)))
{
msgName=newmessagename();
msgName.MessageID=msgDescritionAndID[“正常运行时间(以秒计)”;
msgName.DiagnosticCnt=Convert.ToInt32(infoHash[“正常运行时间(以秒计)”);
msgName.DiagnosticStr=“”;
msgNameList.Add(msgName);
}
//…40多条if语句
返回msgNameList;
}

这对性能确实没有影响,但我想知道是否有更有效的方法来检查字典中的所有键,以及是否将其属性插入MessageName对象并将该对象插入列表。我不知道switch语句是否有助于提高性能

与多个ifs相比,Switch语句确实有助于提高性能

然而,我有一个建议,如果在您的40+语句中多次将相同的属性分配给相同的变量,您可以尝试以下方法:

List<string> toCheckStrings1 = new List<string> { "redis_version", "something similar", };      //you can put all the strings here first
由于您为某些变量指定了不同的属性(例如“正常运行时间(以秒计)”的
DiagnosticCnt
),因此您可以对这些变量进行不同的分组:

List<string> toCheckStrings2 = new List<string> { "uptime_in_seconds", "others", "etc" };
foreach (var match in toCheckStrings2.Intersect(infoHash.Keys))
{
    msgNameList.Add(new MessageName
    {
        MessageID = msgDescritionAndID[match],
        DiagnosticCnt = Convert.ToInt32(infoHash["match"]),
        DiagnosticStr = ""
    });
}
List toCheckStrings2=新列表{“正常运行时间(以秒计)”、“其他”、“等”};
foreach(toCheckStrings2.Intersect(infoHash.Keys)中的变量匹配)
{
msgNameList.Add(新消息名
{
MessageID=msgDescritionAndID[match],
DiagnosticCnt=Convert.ToInt32(infoHash[“匹配]),
DiagnosticStr=“”
});
}
其他情况也是如此。即使它可能是几个
foreach
循环,希望它比45个if语句少得多

编辑


正如在评论中指出的,我上面建议的时间复杂度大约在O(N)左右,而对于您的代码,它将是一堆O(1),基本上是O(1)。因此,如果时间是一个问题(如果你有大量的数据集),那么明智的做法是只使用
if
语句,或者
switch
不需要对所有消息执行字典查找,除非你的字典有很多你不感兴趣的键,在这种情况下,坚持使用你所拥有的键

否则,您已经知道字典中有哪些键,因此可以直接枚举它们

对于那些在检查密钥后当前正在查找值的消息,您将取消另一次查找,因为枚举字典具有免费获取值的额外好处

然后,剩下要做的就是从第二个字典中查找int16,查找要处理的键

您可以更高效地处理此问题,并像这样减少代码基数(假设infoHash只有您想要的密钥):

private List createMsgObject(字典infoHash、字典msgDescritionAndID)
{
MessageName msgName=null;
List msgNameList=新列表();
var msgObjOuter=新消息名();
//不需要对40个变量执行infoHash的o(1)查找。
//您已经有一个包含密钥的列表,所以只需枚举它们。
foreach(infoHash中的KeyValuePair信息)
{
var msg=new MessageName(){MessageID=msgDescritionAndID[info.Key]};
开关(信息键)
{
//首先切换所有int16版本:
案例“redis_版本”:
案例“散列输入消息2”:
案例“散列输入消息3”:
msg.DiagnosticCnt=Convert.ToInt32(infoHash[info.Value]);
打破
//打开从info.Key获取int16的所有消息类型
案例“msg_int_message_1”:
案例“msg_int_message_2”:
msg.DiagnosticCnt=Convert.ToInt32(msgDescritionAndID[info.Key]);
打破
//剩下的一切都是从我们当前的信息中读取价值。
//默认值:
msg.DiagnosticStr=信息值;
打破
}
msgNameList.Add(msgName);
}
返回msgNameList;
}
即使infoHash包含您不感兴趣的密钥,您也可以这样编码:

private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID)
{
    MessageName msgName = null;
    List<MessageName> msgNameList = new List<MessageName>();
    var msgObjOuter = new MessageName();
    // there is no need to perform an o(1) lookup of infoHash for 40 variables. 
    // You already have a list of keys it contains so just enumerate them.
    foreach (KeyValuePair<string, string> info in infoHash)
    {
        var msg = new MessageName() { MessageID = msgDescritionAndID[info.Key] };
        switch (info.Key)
        {
            // switch all of your int16 versions first:
            case "redis_version":
            case "hash_int_message_2":
            case "hash_int_message_3":
                msg.DiagnosticCnt = Convert.ToInt32(infoHash[info.Value]);
                break;
            // switch on all message types getting int16 from info.Key
            case "msg_int_message_1":
            case "msg_int_message_2":
                msg.DiagnosticCnt = Convert.ToInt32(msgDescritionAndID[info.Key]);
                break;
            // switch on all message types that have DiagnosticStr in info.Value;
            case "msg_str_message_1":
            case "msg_str_message_2":
                msg.DiagnosticStr = info.Value;

                break;
            default:    // everything left over we are not interested in
                continue;
                break;

        }
        msgNameList.Add(msgName);
    }
    return msgNameList;
}
private List createMsgObject(字典infoHash、字典msgDescritionAndID)
{
MessageName msgName=null;
List msgNameList=新列表();
var msgObjOuter=新消息名();
//不需要对40个变量执行infoHash的o(1)查找。
//您已经有一个包含密钥的列表,所以只需枚举它们。
foreach(infoHash中的KeyValuePair信息)
{
var msg=new MessageName(){MessageID=msgDescritionAndID[info.Key]};
开关(信息键)
{
//首先切换所有int16版本:
案例“redis_版本”:
案例“散列输入消息2”:
案例“散列输入消息3”:
msg.DiagnosticCnt=Convert.ToInt32(infoHash[info.Value]);
打破
//打开从info.Key获取int16的所有消息类型
案例“msg_int_message_1”:
案例“msg_int_message_2”:
msg.DiagnosticCnt=Convert.ToInt32(msgDescritionAndID[info.Key]);
打破
//打开所有消息类型
private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID)
{
    MessageName msgName = null;
    List<MessageName> msgNameList = new List<MessageName>();
    var msgObjOuter = new MessageName();
    // there is no need to perform an o(1) lookup of infoHash for 40 variables. 
    // You already have a list of keys it contains so just enumerate them.
    foreach (KeyValuePair<string, string> info in infoHash)
    {
        var msg = new MessageName() { MessageID = msgDescritionAndID[info.Key] };
        switch (info.Key)
        {
            // switch all of your int16 versions first:
            case "redis_version":
            case "hash_int_message_2":
            case "hash_int_message_3":
                msg.DiagnosticCnt = Convert.ToInt32(infoHash[info.Value]);
                break;
            // switch on all message types getting int16 from info.Key
            case "msg_int_message_1":
            case "msg_int_message_2":
                msg.DiagnosticCnt = Convert.ToInt32(msgDescritionAndID[info.Key]);
                break;
            // everything left over is reading value from our current info.
            //  default:
                msg.DiagnosticStr = info.Value;
                break;

        }
        msgNameList.Add(msgName);
    }
    return msgNameList;
}
private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID)
{
    MessageName msgName = null;
    List<MessageName> msgNameList = new List<MessageName>();
    var msgObjOuter = new MessageName();
    // there is no need to perform an o(1) lookup of infoHash for 40 variables. 
    // You already have a list of keys it contains so just enumerate them.
    foreach (KeyValuePair<string, string> info in infoHash)
    {
        var msg = new MessageName() { MessageID = msgDescritionAndID[info.Key] };
        switch (info.Key)
        {
            // switch all of your int16 versions first:
            case "redis_version":
            case "hash_int_message_2":
            case "hash_int_message_3":
                msg.DiagnosticCnt = Convert.ToInt32(infoHash[info.Value]);
                break;
            // switch on all message types getting int16 from info.Key
            case "msg_int_message_1":
            case "msg_int_message_2":
                msg.DiagnosticCnt = Convert.ToInt32(msgDescritionAndID[info.Key]);
                break;
            // switch on all message types that have DiagnosticStr in info.Value;
            case "msg_str_message_1":
            case "msg_str_message_2":
                msg.DiagnosticStr = info.Value;

                break;
            default:    // everything left over we are not interested in
                continue;
                break;

        }
        msgNameList.Add(msgName);
    }
    return msgNameList;
}