为了示例,让我们从类定义开始:
public class Person { public string FirstName; public string LastName; public int Age; public int Grade; }
现在让我们假设我有一个List< Person>称为包含3个对象的人:
{"Robby","Goki",12,8} {"Bobby",10,8} {"Sobby",8}
我正在寻找的是一些检索以下单个Person对象的方法:
{null,-1,8}
其中所有对象中相同的字段保留其值,而具有多个值的字段将替换为某些无效值.
我的第一个想法包括:
Person unionMan = new Person(); if (people.Select(p => p.FirstName).Distinct().Count() == 1) unionMan.FirstName = people[0].FirstName; if (people.Select(p => p.LastName).Distinct().Count() == 1) unionMan.LastName = people[0].LastName; if (people.Select(p => p.Age).Distinct().Count() == 1) unionMan.Age = people[0].Age; if (people.Select(p => p.Grade).Distinct().Count() == 1) unionMan.Grade = people[0].Grade;
不幸的是,真正的业务对象有比4个更多的成员,这对于第一次看到别人看的东西来说既乏味又难以理解.
我还考虑过以某种方式利用反射将这些重复的检查和赋值放在一个循环中:
string[] members = new string[] { "FirstName","LastName","Age","Grade" }; foreach (string member in members) { if (people.Select(p => p.**member**).Distinct().Count() == 1) unionMan.**member** = people[0].**member**; }
但是**成员**将会反射,这将允许检索和存储该特定成员(假设有可能).
虽然第一个解决方案可行,而我假设的第二个解决方案可行,但有没有人有更好的替代解决方案来解决这个问题?如果没有,如上所述使用反射是否可行?
解决方法
为了计算不同的成员,做一个独特的所有值是没有效率的.您有一个快捷方案,其中在与第一个项目的成员不具有相同值的任何后续项目中查找一个值意味着您具有该列的无效状态.
这样的东西应该可以工作,但是如果任何成员是数组,需要做更多的工作,需要递归评估或其他更复杂的逻辑(注意我没有测试过这个):
public static T UnionCombine<T>(this IEnumerable<T> values) where T : new() { var newItem = new T(); var properties = typeof(T).GetProperties(); for (var prop in properties) { var pValueFirst = prop.GetValue(values.First(),null); var useDefaultValue = values.Skip(1).Any(v=>!(Object.Equals(pValueFirst,prop.GetValue(v,null)))); if (!useDefaultValue) prop.SetValue(newItem,pValueFirst,null); } return newItem; }