【问题标题】:Include properties based on conditions in anonymous types在匿名类型中包含基于条件的属性
【发布时间】:2014-12-30 17:41:10
【问题描述】:

假设我有以下匿名类型

var g = records.Select(r => new
{                    
    Id = r.CardholderNo,
    TimeIn = r.ArriveTime,
    TimeOut = r.LeaveTime,
});

是否可以执行以下操作:

var g = records.Select(r => new
{                    
    Id = r.CardholderNo,
    if (condition) 
    {
        TimeIn = r.ArriveTime;
    },
    TimeOut = r.LeaveTime,
    //many more properties that I'd like to be dependant on conditions.
});

如何根据条件实现匿名类型?

【问题讨论】:

  • var g = records.Select(r => new { Id = r.CardholderNo, TimeIn = condition?r.ArriveTime:null TimeOut = r.LeaveTime });
  • 不,这是不可能的。匿名是强类型的。当condition 在运行时被解析时,你会期待什么行为?
  • 我认为演员可以解决问题@pwas
  • 当您不知道对它有什么期望时,使用这样的对象是不可能或非常困难的。您必须首先检查该属性是否存在,然后检查它是否具有值。

标签: c# .net anonymous-types


【解决方案1】:

您可以使用ternary operator: ?: 来做到这一点

语法是这样的:

TimeIn = condition ? r.ArriveTime : (DateTime?)null // Or DateTime.Min or whatever value you want to use as default

更新

在考虑了你的问题几分钟后,我想出了以下你永远不应该使用的代码;)

using System;

class Program
{
    static void Main(string[] args)
    {
        DateTime dt = DateTime.Now;

        bool condition = true;

        dynamic result = condition ?
            (object)new
            {
                id = 1,
                prop = dt
            }
            :
            (object)new
            {
                id = 2,
            };

        Console.WriteLine(result.id);
        if (condition) Console.WriteLine(result.prop);
    }
}

这个代码不应该在生产环境中使用,因为它的可读性很差,而且很容易出错。但是,作为学习语言的例子,它非常好。

【讨论】:

  • r.ArriveTime(或 null)必须转换为可空类型 (DateTime?)r.ArriveTime) : null - 否则表达式将在编译时失败。
  • 他实际上期望的是属性“TimeIn”应该根据条件添加到匿名类型中。如果条件评估为假,他不想将该属性添加到类型中
【解决方案2】:

不直接使用if 语句,但您可以使用三元运算符(假设TimeIn 的类型为DateTime):

var g = records.Select(r => new
{

    Id = r.CardholderNo,
    TimeIn = condition ? r.ArriveTime : (DateTime?)null;
    TimeOut = r.LeaveTime
});

请注意,这将使该属性始终出现在您的匿名类型中。如果这不是你想要的行为,那么你不能这样做。

我建议考虑代码的可读性,而不仅仅是“我怎样才能缩短这几行代码使其看起来整洁”。

【讨论】:

  • r.ArriveTime 如果是不可空类型,则必须强制转换为可空。否则? 运算符将在编译时失败。
【解决方案3】:

没有。匿名类型就像任何其他类型一样。它有一个固定的属性列表。您不能动态添加或删除属性。

我建议将属性设置为null,就像在其他答案中一样,或者使用Dictionary 添加相关属性及其值。

【讨论】:

    【解决方案4】:

    如果您在创建匿名类型时确实需要 if(或任何其他语句),您可以尝试这个不太漂亮的解决方案:

    var g = records.Select(r => new
    {
        Id = r.CardholderNo,
        TimeIn = new Func<DateTime?, DateTime?>(x =>
                {
                if (...)
                    return x;
                else
                    return null;
                }).Invoke(r.ArriveTime),
        TimeOut = r.LeaveTime,
    });
    

    【讨论】:

    • 您真的想使用这样的代码来避免在创建对象之前使用if 语句吗?
    • 正如我在回答中提到的 - 就个人而言,我不会。但这是一种选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多