有没有一种高效的方法来使用两个变量进行选择语句?

5
在我的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);
    }
}

1
/* ... code ... */ 是什么?您可以使用 LINQ 来执行像这样的查询,假设代码中包含了它。 - Cyral
我是以更通用的意义在说话。这些是通过表单提交发送到函数中的参数。我会修改我的发布的问题以提供这个上下文。 - user4864716
你可以首先创建一个类似 If(check("campus","ASC"))... 的方法,然后将字符串添加到数组中并循环遍历... for(i...) {if(check(strby[i],strdir[i])) },或者如果您不喜欢两个数组,可以为其创建一个特殊的对象。 - ElDuderino
4个回答

4

您可以在 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<>。如果它实际上返回一个IEnumerable<>,那么扩展方法需要接受一个IEnumerable<TSource> source参数,并返回一个IOrderedEnumerable<TSource>
然后可以按照以下方式使用:
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<FourCourseAudit> GetResultsByFilter(string filter)。您建议将其放在模型中还是控制器中? - user4864716
假设这是一个数据库查询,最好让GetResultsByFilter返回IQueryable<FourCourseAudit>。这将允许OrderBy在数据库级别上作为SQL ORDER BY执行(请参见https://dev59.com/TnE85IYBdhLWcg3wOw_s)。我可能会将`GetResultsByFilter`方法放在控制器中,除非它在多个控制器中使用。 - Phil Ross
我创建了IEnumerable,以便它能够满足MVC视图的更大需求。你提出了一个很好的观点,但现在我又重新进入了打地鼠的世界,在这个世界里,做出一项改变会导致其他地方出现问题。 - user4864716
@Rubix_Revenge IQueryable<T> 扩展了 IEnumerable<T>,因此您应该能够在任何需要 IEnumerable<T> 的地方使用实现 IQueryable<T> 的实例。 - Phil Ross

2

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

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

1
我会使用三元运算符使其更加紧凑和易于阅读,代码如下。
这样也可以减少一些布尔检查,因为它不会重复任何一个。
    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);
        }
    }

我没有想到三元运算符,但我喜欢它。它易于阅读和创建,现在我看到它后,我可以很容易地理解它的工作原理。 - user4864716
很高兴能够帮忙。它们非常有用。 - deathismyfriend

0

我的看法:

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

可能会有一些错误,我目前手头没有集成开发环境。


由于我仍处于语言学习曲线上,这对我来说肯定是新的。但这给了我更多的材料去思考。谢谢。 - user4864716

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接