没有开关的替代方式/如果否则 - C#

时间:2013-12-19 06:42:00

标签: c# linq-to-sql coding-style

我有以下C#代码,代码中的一般情况是根据功能编写if / else或switch。

在同一个函数中我写了多行来增加代码复杂度。

有没有其他更好的方法我可以在没有其他的情况下实施?欢迎任何其他建议。

//Sample Piece of code to highlight my scenario. may have syntax errors
IEnumerable<lst> fnc(string category)
{
    using(Context sample = new Context())
    {
        if (category == "A")
        {
            return from T1  in  sample.TableName 
                   join T2 in sample.A on T1.id = T2.id
                   where cat= category
                   select T1
        }
        else if (category == "B")
        {
            return from T1  in  sample.TableName 
                   join T2 in sample.B on T1.Eid = T2.id
                   where cat= category
                   select T1
        }
        else if (category == "C")
        {
            return from T1  in  sample.TableName 
                   join T2 in sample.C on T1.id = T2.id
                   where cat= category
                   select T1
        }
        // ...
        else if (category == "I")
        {
            return from T1  in  sample.TableName 
                   join T2 in sample.I on T1.id = T2.id
                   where cat= category
                   select T1
         }
         else
         { /* return ... */ }
    }
}

感谢。

6 个答案:

答案 0 :(得分:3)

您可以构建一个字典来存储条件:

var array = new[] {10, 20, 30};
var conditions = new Dictionary<string, Func<int, bool>>
{
    {"A", input => input > 10},
    {"B", input => input > 20}
};

if (conditions.ContainsKey(category))
{
    return array.Where(conditions[category]);
}
else
{
    // else :>
}

int必须替换为您在可枚举中存储的类型。

答案 1 :(得分:2)

IEnumerable<lst> fnc(string category)
{
    return JoinByCategory(sample.TableName, category)
             .Where(t1 => t1.cat == category);
}

private IQueryable<T1> JoinByCategory(IQueryable<T1> outer, string category)
{
   switch(category)
   {
      case "A": return outer.Join(sample.A, t1=> t1.id, a=> a.id, (t1,a)=> t1);
      case "B": return outer.Join(sample.B, t1=> t1.Eid, b=> b.id, (t1,b)=> t1);
      ...
      default:
         throw new ArgumentException();
   }
}

答案 2 :(得分:1)

您可以为LINQ to Objects创建Dictionary<string, Expression<Func<Entity, bool>>>(或Dictionary<string, Func<CollectionItem, bool>>)并使用它代替if / elseswitch / {{1} }:

case

答案 3 :(得分:1)

您可以使用Dynamic LINQ。创建一个包含所有条件的数组。然后根据'Category'条件获取数组索引并在LINQ Expression中使用它。

答案 4 :(得分:1)

正如您所提到的,对于不同的条件,您有不同的连接,但是,您仍然可以将所有查询放入带字符串键的字典中,例如:

    private static Dictionary<string, Func<DataContext, IEnumerable<lst>>> functions = new Dictionary<string, Func<DataContext, IEnumerable<lst>>>() 
    { 
        {"A", 
         delegate(DataContext dbCtx)
         {
            return new List<lst>(); // your query here...
         }
        },
        {"B", 
         delegate(DataContext dbCtx)
         {
            return new List<lst>();
         }
        },
        {"C", 
         delegate(DataContext dbCtx)
         {
            return new List<lst>();
         }
        }
    };

    public IEnumerable<string> fnc(string category)
    {
        if (!(functions.ContainsKey(category)))
        {
            throw new NotImplementedException();
        }

        using(Context sample = new Context()
        {
            return functions[category].Invoke(sample);
        }
    }
希望它有所帮助...

答案 5 :(得分:0)

可以使用Map扩展方法替换switch命令:

return externalCode
    .Map("A", from T1 in sample.TableName
            join T2 in sample.A on T1.id = T2.id 
            where cat = category
            select T1)
    .Map("B", from T1 in sample.TableName
            join T2 in sample.B on T1.Eid = T2.id 
            where cat = category
            select T1)
    .Map("C", from T1 in sample.TableName
            join T2 in sample.C on T1.id = T2.id 
            where cat = category
            select T1)
    .Map("I", from T1 in sample.TableName
            join T2 in sample.I on T1.id = T2.id 
            where cat = category
            select T1)
    .Else(...)

更多示例和来源:here