简体   繁体   中英

How can I return different DataTypes in lambda expression?

I want to obtain the following functionality. But since I have to return different datatypes, the method isn't allowed. What will I do in this context?

.OrderBy(X =>
             {
                switch (OrderByColumn)
                {
                   case "":
                      return X.a.CreatedOn;
                   case "BookCategoryName":
                      return X.a.BookCategoryName;
                   case "BookCategoryDescription":
                      return X.a.BookCategoryDescription;
                }
                return X.a.CreatedOn;
             });

Or any other suggestion to get this functionality?

I suggest you to change your logic to build query instead of making such logic in lambda:

build query before like:

var query = list.Where(...);

if(OrderByColumn=="BookCategoryName")
{
   query = query.OrderBy(x=>x.a.BookCategoryName);
}
....

at the end:

var result = query.ToList(); //for e.g.

it will work as you want and look much cleaner

For each data type that your current lambda might return, use a separate block to define the ordering, and for any options that don't use that return type, return a constant.

Guessing, for the moment, that CreatedOn is a DateTime and BookCategoryName and BookCategoryDescription are strings, it would be something like:

.OrderBy(X =>
             {
                switch (OrderByColumn)
                {
                   case "":
                      return X.a.CreatedOn;
                   case "BookCategoryName":
                      return new DateTime(1900,1,1);
                   case "BookCategoryDescription":
                      return new DateTime(1900,1,1);
                }
                return X.a.CreatedOn;
             })
.ThenBy(X =>
             {
                switch (OrderByColumn)
                {
                   case "":
                      return "";
                   case "BookCategoryName":
                      return X.a.BookCategoryName;
                   case "BookCategoryDescription":
                      return X.a.BookCategoryDescription;
                }
                return "";
             });

(Of course, the constant values could be moved out to be real constants or variables, etc, but I wanted to make the above snippet self contained)

,Another option is to extract the ordering field selection itself to a separate method, like this:

public IEnumerable<Data> SelectData(IEnumerable<Data> data, Func<Data, bool> predicate)
{
    return data
        .Where(predicate)
        .OrderBy(GetCurrentOrderingField);
}

private IComparable GetCurrentOrderingField(Data x)
{
    switch (OrderByColumn)
    {
        case "BookCategoryName":
            return x.a.BookCategoryName;

        case "BookCategoryDescription":
            return x.a.BookCategoryDescription;
    }

    return x.a.CreatedOn;
}

This, of course, for fields implementing IComparable interface.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM