LINQ 查询中使用的 C# 三元运算符

Posted

技术标签:

【中文标题】LINQ 查询中使用的 C# 三元运算符【英文标题】:C# Ternary Operator used in LINQ query 【发布时间】:2013-11-14 12:12:10 【问题描述】:

是否可以使用三元运算符来体现这个逻辑?

if (a = 1)

    somevalue = "hello";
 
else if (a = 2)

    someValue = "world";

else if (a = 3)

    someValue = "hellWorld";

我在 LINQ 查询中执行以下操作:

using (var data = new DAL())

    var result = data.Holidays.AsNoTracking()
                 .Where(x => x.RequesterId == userId)
                 .Select(x => new HolidayModel
                 
                     HolidayId = x.HolidayId,
                     FromDate = x.FromDate,
                     ToDate = x.ToDate,
                     AuthorisationStatus = x.InternalHolidayStatus == 1 ?
                         HolidayAuthStatus.Pending :
                         HolidayAuthStatus.Rejected,
                     DateModified = x.ModifiedDate
                 ).ToList();

    return Json(result.ToDataSourceResult(request));

HolidayAuthStatus 是一个枚举,其中包含三个值(Pending (1)、Authorised (2) 和 Rejected (3));我想在分配AuthorisationStatus 的值时在代码中反映这一点。

【问题讨论】:

显然你已经在使用它了,有什么问题吗?此外,如果HolidayAuthStatus 对应于AuthorisationStatus,您可以直接进行转换。 这是 LINQ-to-Objects、LINQ-to-SQL 还是 LINQ-to-Entities? 【参考方案1】:

改成这个

AuthorisationStatus = (HolidayAuthStatus)x.InternalHolidayStatus

如果您的 HolidayAuthStatus 的整数值与 InternalHolidayStatus 值匹配,它将起作用。这里的三元运算符看起来很糟糕。如果您的状态码不匹配,最好让函数接受int status 并返回HolidayAuthStatus

HolidayAuthStatus GetStatus(int status)

    if(status == 1) return HolidayAuthStatus.Pending;
    if(status == 2) return HolidayAuthStatus.Authorised;
    if(status == 3) return HolidayAuthStatus.Rejected;
    return HolidayAuthStatus.Unknown; // for e.g.

并像这样使用它:

AuthorisationStatus = GetStatus(x.InternalHolidayStatus)

编辑:

正如@James 所说,该方法仅适用于 Linq-to-object 而不是 Linq-to-entities

【讨论】:

方法方法很可能只适用于 LINQ To Objects。 @James 好点我还没有看到DAL() 在使用中,我会写在我的回答中,谢谢 @wudzik 谢谢,这是一种巧妙的方法,但它在 LINQ 查询中不起作用。返回此错误:LINQ to Entities 无法识别方法 'Timeshet.Web.Models.Enum.HolidayAuthStatus GetStatus(Int32)' 方法,并且此方法无法转换为商店表达式 @t_plusplus 是的,我现在知道了,因为它是 linq-to-entities 我错过了这一点,James 指出了这一点。第一种方法适用于 linq-to-entites,仅次于 linq-to-objects。使用(HolidayAuthStatus)x.InternalHolidayStatus检查第一个答案 @t_plusplus 您仍然可以使方法工作,但是,您需要实现查询并然后进行投影,即data.Holidays.AsNoTracking().Where(...).AsEnumerable().Select(...).ToList();【参考方案2】:

是的,这是可能的。我认为很难用三元运算符获得运算符优先级,所以我更喜欢使用括号:

AuthorizationStatus = x.InternalHolidayStatus == 1 ?
    HolidayStatus.Pending :
    (x.InternalHolidayStatus == 2 ?
        HolidayStatus.Rejected : 
        (x.InternalHolidayStatus == 3 ?
            HolidayStatus.Authorized : 
            HolidayStatus.Invalid))

由于这是到枚举的映射,因此也可以按照@wodzik 的建议使用强制转换,前提是可以且可行地为枚举值使用与数据库中相同的值。

要使用它,您必须明确地为枚举赋值

public enum HolidayStatus

    Pending = 1,
    Rejected = 2,
    Authorized = 3

那么你可以这样做:

AuthorizeStatus = (HolidayStatus)x.InternalHolidayStatus

【讨论】:

您有更好的格式化建议吗?不幸的是,C# 中没有 switch-case 运算符,只有不能在 LINQ 查询中使用的语句。 我不会嵌套三元运算符。 @RichardEv 嵌套三元运算符有什么问题?您失去了一些可读性,但它仍然功能上正确。 问题是专门询问是否可以使用三元运算符,这就是我的答案。我知道代码很难看,但对于 Linq-to-Entities,不可能将表达式分解为单独的方法。 对我(以及我最近合作过的团队)来说,一切都与可读性有关。但是你是对的,三元是我们所要求的......而且我知道使用 Linq-to-Entities 时存在限制。

以上是关于LINQ 查询中使用的 C# 三元运算符的主要内容,如果未能解决你的问题,请参考以下文章

C# 中哪个三元运算符最流行和最常用? [关闭]

C# - 为啥我不能在字符串中使用三元运算符? [复制]

在 C# 中创建元组时编译错误,没有括号包围三元运算符

C#中的三元运算符

三元?运算符与 C# 中的传统 If-else 运算符 [重复]

Delphi - 相当于 C# 的三元运算符? [复制]