【问题标题】:how to update all the fields with specific value in a list of object如何更新对象列表中具有特定值的所有字段
【发布时间】:2017-06-27 03:20:58
【问题描述】:

我有一个对象列表,我想将所有“null”字段更新为 string.empty。

代码如下:

public class Class1
{
    public string P1 { get; set; }
    public string P2 { get; set; }
    public string P3 { get; set; }
}

我想要一个代码,在所有字段中找到所有空值并将值更改为 string.empty

     static void Main(string[] args)
    {

        var list= new List<Class1>();
        var class1 = new Class1 {P1 = "P1-1", P2 = "P2-1", P3="null"};
        list.Add(class1);
        var class2 = new Class1 { P1 = "P1-2", P2 = "P2-2", P3 = "null" };
        list.Add(class2);

    }

所以我需要找到 class1.P3 和 class2.P3 并替换它们的值。

谢谢

【问题讨论】:

  • 请记住null 与“null”不同。
  • 真的,在我的情况下,我收到的 json 数据是“null”而不是 null

标签: c# list linq reflection


【解决方案1】:

您可以像这样编写一个简短的通用函数:

private static IEnumerable<TSource> ReplaceValues<TSource>(IEnumerable<TSource> source, object oldValue,
    object newValue)
{
    var properties = typeof(TSource).GetProperties();
    foreach (var item in source)
    {
        foreach (var propertyInfo in properties.Where(t => Equals(t.GetValue(item), oldValue)))
        {
            propertyInfo.SetValue(item, newValue);
        }
        yield return item;
    }
}

这比你的更有效,因为你的集合类型是TSource,这意味着里面的所有类型都将具有相同的属性。获取和缓存这些属性将加快该过程,因为您只调用一次Type.GetProperties(),而不是操作和过滤这些结果。

更新

正如下面Ivan Stoev 的评论部分所讨论的那样,让该方法只修改集合而不返回任何值会更合适:

private static void ReplaceValues<TSource>(IEnumerable<TSource> source, object oldValue,
    object newValue)
{
    var properties = typeof(TSource).GetProperties();
    foreach (var item in source)
    {
        foreach (var propertyInfo in properties.Where(t => Equals(t.GetValue(item), oldValue)))
        {
            propertyInfo.SetValue(item, newValue);
        }
    }
}

【讨论】:

  • 您需要按值比较字符串。使用Equals()
  • @SLaks 好主意,虽然涉及装箱/拆箱,但传递IEqualityComparer&lt;T&gt; 应该更好,我将编辑答案。
  • 看起来不错。为了获得最佳性能,请在静态类中跨调用缓存属性:stackoverflow.com/q/686630/34397
  • (1) 我想到了你刚刚修复的错误 :) (2) 虽然有一个同样yields 的变异方法是不自然的。这个名字暗示了 action 并且很容易忘记 yielding 方法在它们得到foreach-ed、ToList()-ed、Count()-ed 等之前什么都不做。基本上它是一种主要目的的方法是副作用,不符合 LINQ(uery) 精神。
  • 是的,但是Select 将源元素转换(映射、投影)为目标元素(通过选择属性或创建 new 对象)。虽然您的方法正在改变源。通常人们不会期望像foreach (var x in something) 这样的代码会改变x 的内容。没有 LINQ 方法可以做到这一点,尽管它们可以被滥用来做到这一点,这最终只会给滥用它们的人带来问题——当人们尝试使用“简洁”的 LINQ 时,我在 SO 上看到过很多次Select + 其他操作符来执行突变并忘记它需要被执行:)
【解决方案2】:

这会解决它:

   static void Main(string[] args)
    {

        var list= new List<Class1>();
        var class1 = new Class1 {P1 = "P1-1", P2 = "P2-1", P3="null"};
        list.Add(class1);
        var class2 = new Class1 { P1 = "P1-2", P2 = "P2-2", P3 = "null" };
        list.Add(class2);


        foreach (var item in list)
        {
            var props2 = from p in item.GetType().GetProperties()
                        let attr = p.GetValue(item)
                        where attr != null && attr.ToString() == "null"
                        select p;

            foreach (var i in props2)
            {
                i.SetValue(item, string.Empty);
            }
        }
    }

更新::::

这是一种更有效的方法。

    static void Main(string[] args)
    {

            var list = new List<Class1>();
            var class1 = new Class1 {P1 = "P1-1", P2 = "P2-1", P3 = "null"};
            list.Add(class1);
            var class2 = new Class1 {P1 = "P1-2", P2 = "P2-2", P3 = "null"};
            list.Add(class2);



           var updatedList=  ReplaceValues(list, "null", string.Empty);

    }

    private static IEnumerable<TSource> ReplaceValues<TSource>
    (IEnumerable<TSource> source, object oldValue,
    object newValue)
    {
        var properties = typeof(TSource).GetProperties();
        var sourceToBeReplaced = source as TSource[] ?? source.ToArray();
        foreach (var item in sourceToBeReplaced)
        {
            foreach (var propertyInfo in properties.Where(t => Equals(t.GetValue(item), oldValue)))
            {
                propertyInfo.SetValue(item, newValue);
            }
        }

        return sourceToBeReplaced;
    }

【讨论】:

  • 只获取一次属性会更有效率。
  • 你会怎么做?
  • 只缓存结果。
  • ...您刚刚回答了自己的问题吗?
  • @Deadzone,你能解释一下你会怎么做吗?你会在这里缓存什么?
猜你喜欢
  • 2015-03-11
  • 2014-11-04
  • 2012-07-13
  • 1970-01-01
  • 2016-07-10
  • 2021-12-12
  • 2010-11-08
  • 2021-04-23
  • 2017-09-13
相关资源
最近更新 更多