为了示例,让我们从类定义开始:
public class Person
{
public string FirstName;
public string LastName;
public int Age;
public int Grade;
}
Run Code Online (Sandbox Code Playgroud)
现在让我们假设我有一个包含3个对象的List<Person>被调用者people:
{"Robby", "Goki", 12, 8}
{"Bobby", "Goki", 10, 8}
{"Sobby", "Goki", 10, 8}
Run Code Online (Sandbox Code Playgroud)
我正在寻找的是一些检索以下单个Person对象的方法:
{null, "Goki", -1, 8}
Run Code Online (Sandbox Code Playgroud)
其中所有对象中相同的字段保留其值,而具有多个值的字段将替换为某些无效值.
我的第一个想法包括:
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;
Run Code Online (Sandbox Code Playgroud)
遗憾的是,真正的业务对象有很多更多的成员超过四个,这是既繁琐的编写和压倒别人看到的第一次.
我还考虑过以某种方式利用反射将这些重复的检查和赋值放在一个循环中:
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**;
}
Run Code Online (Sandbox Code Playgroud)
其中**构件**将然而反射将允许该特定部件的检索和存储(假设它是可能的).
虽然第一个解决方案可行,而我假设的第二个解决方案可行,但有没有人有更好的替代解决方案来解决这个问题?如果没有,如上所述使用反射是否可行?
为了计算不同的成员,做一个独特的所有值是没有效率的.您有一个快捷方案,其中在与第一个项目的成员不具有相同值的任何后续项目中查找一个值意味着您具有该列的无效状态.
这样的东西应该可以工作,但是如果任何成员是数组,需要做更多的工作,需要递归评估或其他更复杂的逻辑(注意我没有测试过这个):
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;
}
Run Code Online (Sandbox Code Playgroud)