【问题标题】:Is there an efficient way to do a selection statement with two variables?有没有一种有效的方法来做一个带有两个变量的选择语句?
【发布时间】:2015-06-20 23:26:24
【问题描述】:

在我的 C# 代码中,我需要计算两个非空变量。我制定了一组 if-else if 语句,但在我看来,它看起来很难看,而且有点过于草率,即使它是正确的。

我查看了MSDN Library,只看到了基于单个变量的选择示例。

有没有更简洁、更简洁的方法来达到同样的效果?

更新:我填写了代码以提供更多上下文。再看这个,也许我可以直接根据参数来操作 linq 查询。但是,我提出的问题我想关注的通用问题:选择,而不是选择后使用的代码。

public ActionResult Index(string searchBy, string orderBy, string orderDir)
{
    var query = fca.GetResultsByFilter(searchBy);

    if (orderBy == "Campus" && orderDir == "Asc")
    {
        query = query = query.OrderBy(s => s.Campus).ThenBy(s => s.Student_Name);
    }
    else if (orderBy == "Campus" && orderDir == "Desc") 
    {
    query = query.OrderByDescending(s => s.Campus);
    }
    else if (orderBy == "Student Name" && orderDir == "Asc")
    {
        query = query = query.OrderBy(s => s.Student_Name);
    }
    else if (orderBy == "Student Name" && orderDir == "Desc")
    {
        query = query.OrderByDescending(s => s.Student_Name);
    }
    else if (orderBy == "Course Count" && orderDir == "Asc")
    {
    query = query.OrderBy(s => s.Course_Count);
    }
    else if (orderBy == "Course Count" && orderDir == "Desc")
    {
    query = query.OrderByDescending(s => s.Course_Count);
    }
}

【问题讨论】:

  • /* ... code ... */ 是什么?你可以使用 LINQ 来执行这样的查询,假设这是代码中的内容。
  • 我说的是一般意义上的。这些是通过表单提交发送到函数中的参数。我将修改我发布的问题以提供该上下文。
  • 您可以首先创建一个像 If(check("campus","ASC"))... 这样的方法,然后将您的字符串添加到一个数组中并循环...for(i. ..) {if(check(strby[i],strdir[i])) }....如果您不喜欢两个数组,请为其创建一个特殊对象...

标签: c# linq


【解决方案1】:

您可以在IQueryable 上创建一个扩展方法来处理OrderByOrderByDescending 的排序:

public static class QueryableExtensions
{
    public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey>
        (this IQueryable<TSource> source,
        Expression<Func<TSource, TKey>> keySelector,
        string orderDir)
    {
        return orderDir == "Desc" 
                        ? source.OrderByDescending(keySelector)
                        : source.OrderBy(keySelector);
    }
}

我假设您的 GetResultsByFilter 方法返回一个 IQueryable&lt;&gt;。如果它实际上返回一个IEnumerable&lt;&gt;,那么扩展方法将需要一个IEnumerable&lt;TSource&gt; source 参数并返回一个IOrderedEnumerable&lt;TSource&gt;

然后可以按如下方式使用:

public ActionResult Index(string searchBy, string orderBy, string orderDir)
{
    var query = fca.GetResultsByFilter(searchBy);

    switch (orderBy)
    {
        case "Campus":
            query = query.OrderByWithDirection(s => s.Campus, orderDir);
            break;
        case "Student Name":
            query = query.OrderByWithDirection(s => s.Student_Name, orderDir);
            break;
        case "Course Count":
            query = query.OrderByWithDirection(s => s.Course_Count, orderDir);
            break;
    }

    if (orderBy == "Campus" && orderDir == "Asc")
    {
        // The Campus Asc case was also ordered by Student_Name in the question.
        query = query.ThenBy(s => s.Student_Name);
    }
}

【讨论】:

  • 好问题 GetResultsByFilter(string) 调用 IEnumerable&lt;FourCourseAudit&gt; GetResultsByFilter(string filter)。你会建议把它放在模型中还是控制器中?
  • @Rubix_Revenge 假设这是一个数据库查询,最好让GetResultsByFilter返回IQueryable&lt;FourCourseAudit&gt;。这将允许OrderBy 在数据库级别作为 SQL ORDER BY 执行(请参阅stackoverflow.com/q/2876616)。我可能会将GetResultsByFilter 方法放在控制器中,除非它在多个控制器中使用。
  • 我制作了 IEnumerable 以便满足 MVC 视图的更大需求。你提出了一个很好的观点,但现在我重新进入了打地鼠的世界,在那里进行一次更改会导致其他地方出现问题。
  • @Rubix_Revenge IQueryable&lt;T&gt; 扩展了IEnumerable&lt;T&gt;,因此您应该能够在任何需要IEnumerable&lt;T&gt; 的地方使用实现IQueryable&lt;T&gt; 的实例。
【解决方案2】:

C不确定这是否更好,只是不同。

switch (orderDir)
{
    case "Asc":
        Switch (orderBy)
        {
            case "Campus":
                //Code here for Campus orderBy and Asc orderDir
                break;
            case "Student Name":
                //Code here for Student Name orderBy and Asc orderDir
                break;
            case "Course Count":
                //Code here for Course Count orderBy and Asc orderDir
                break;
        }
        break;
    case "Desc":
        Switch (orderBy)
        {
            case "Campus":
                //Code here for Campus orderBy and Desc orderDir
                break;
            case "Student Name":
                //Code here for Student Name orderBy and Desc orderDir
                break;
            case "Course Count":
                //Code here for Course Count orderBy and Desc orderDir
                break;
        }
        break;
}

【讨论】:

    【解决方案3】:

    我会使用三元运算符来使这样更紧凑,更易于阅读。

    这也将减少一些布尔检查,因为它不会重复任何一个。

        public ActionResult Index(string searchBy, string orderBy, string orderDir)
        {
            var query = fca.GetResultsByFilter(searchBy);
    
            if (orderBy == "Campus")
            {
                query = (orderDir == "Asc") ? query.OrderBy(s => s.Campus).ThenBy(s => s.Student_Name) :
                    query.OrderByDescending(s => s.Campus);
            }
            else if (orderBy == "Student Name")
            {
                query = (orderDir == "Asc") ? query.OrderBy(s => s.Student_Name) : query.OrderByDescending(s => s.Student_Name);
            }
            else if (orderBy == "Course Count")
            {
                query = (orderDir == "Asc") ? query.OrderBy(s => s.Student_Name) : query.OrderByDescending(s => s.Course_Count);
            }
        }
    

    【讨论】:

    • 我没有想到三元运算符,但我喜欢它。它易于阅读和创建,现在我可以很容易地看到它是如何工作的。
    • 很高兴为您提供帮助。它们非常有用。
    【解决方案4】:

    我的看法:

    public interface IOrder {
        void perform(Query query)
    }
    
    public abstract class AbstractOrder : IOrder {
    
        protected string orderString;
    
        public AbstractOrder(string orderString) {
             this.orderString = orderString;
        }
    }
    
    public class OrderAsc {
    
        public OrderAsc(string orderString) : base(orderString) {
        }
    
        public Query perform(Query query) {
            query = query.OrderBy(s => s.Course_Count); //here you still have to do a mapping between orderString and your db field s.Course_count 
            return query;
        }
    }
    
    public class OrderDesc {
    
        public OrderDesc(string orderString) : base(orderString) {
        }
    
        public Query perform(Query query) {
            query = query.OrderByDescending(s => s.Course_Count); //here you still have to do a mapping between orderString and your db field s.Course_count, or maybe it's equal, then you can just replace it.
            return query;
        }
    }
    

    然后...

    IList<IOrder> list = new List<IOrder>() {new OrderAsc("Campus"), new OrderDesc("Student Name")}
    
    foreach(IOrder o in list) {
        query = o.perform(query);
    }
    

    其中可能有一些错误,我手头没有 IDE。

    【讨论】:

    • 因为我还在语言学习曲线上,这对我来说肯定是新的。但这给了我更多的材料来咀嚼。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多