How to validate values in a list of object? - c#

I have a List<ObjectA> populated.
Class ObjectA has two properties -string property1 bool? property2
[1]I need to loop through the entire list to check if property1 contains a particular string say 'xyz'.
[2] I need to check if value of property2 is true(which i believe i can figure out after getting to know how to handle [1])
thanks
Adarsh

With List<T> you can also use its method TrueForAll:
bool valid = list.TrueForAll(a => a.property1.Contains("xyz") && a.property2);
This will work on any version of .NET >= 2.0. You also can use LINQ as #Hassan suggested:
bool valid = list.All(a => a.property1.Contains("xyz") && a.property2);
That will work on .NET >= 3.5. Benefit of this option is ability to work with any enumerable source (i.e. if you'll change list to ICollection, or some other enumerable type).

if you want to make sure if all elements of a particular collection satisfy a condition you can use All method in Linq, like this:
new List<MyClass>().All(m => m.StringProp.Contains("ss") && m.IsValid == true)

Use LINQ:
List<ObjectA> list;
//Check for string
if (list.Any(a => a.property1.Contains("xyz")))
{
}
// Check for true
if (list.Any(a => a.property2 ?? false))
{
}
If you need to get the objects that satisfies your conditions, use list.Where(...)

There are several possible checks and results you can easily get.
void Main()
{ //ignore Dump() method
var list = new List<ObjectA>()
{
new ObjectA("name1", true),
new ObjectA("name2", true),
new ObjectA("name3", null),
new ObjectA("name4", false),
new ObjectA("name5", null),
new ObjectA("name6", false),
new ObjectA("name7", true)
};
//check if all Items are valid
var allItems = list.All(m => m.Name.Contains("ss") && m.valid == true); // false
//only get valid items (name contains name AND true)
var validItems = list.Where (l => l.Name.Contains("name") && l.valid == true).Dump();
//get all items which are invalid
var nonvalidItems = list.Where(l =>!(l.Name.Contains("name")) || l.valid != true).Dump();
}
public class ObjectA
{
public ObjectA(string name, bool? _val)
{
this.Name = name;
if(_val.HasValue)
this.valid = _val;
}
public string Name { get; set; }
public bool? valid { get; set; }
}

Related

Dynamically checking IList<T>

I have a class file named ParentPropertyAttribute with a Type Property as below:
public Type PropertyType { get; set; }
In one of my class, I need to do some work based on the type passed.
Right now, I am using if else condition as below:
if (parentPropertyAttribute.PropertyType == typeof(string))
{
return (parentList as IList<string>).Select(item => new SelectItem() { Value = item, Text = item }).OrderBy(selectItem => selectItem.Text);
}
else if (parentPropertyAttribute.PropertyType == typeof(XYZ))
{
return (parentList as IList<XYZ>).Select(x=> new SelectItem() { Value = item, Text = item }).OrderBy(selectItem => selectItem.Text);
}
The issue with the above is in future if there is any other type the if else case gets on increasing.
Is there an optimized way to dynamically assign the type (string/XYZ in this case) to achieve this.
Any input is appreciated.
Regards.
Since the only thing you're using with the IList<> interface is coming from the IEnumerable<> interface, there's a chance you could just do something like this:
return ((IEnumerable)parentList).Cast<object>()
.Select(item => new SelectItem { Value = item, Text = item.ToString() })
.OrderBy(selectItem => selectItem.Text)
.ToList();
This depends on all the valid types in your lists having ToString() implementations that are appropriate for this purpose, though.
Note that the ((IEnumerable)parentList).Cast<object>() could be simplified to ((IEnumerable<object>)parentList) if you know none of the types are Value Types (which need boxing to convert into objects).
Of course you can. You just need more generics in your code.
Please refer to this example:
class SmartListItem
{
public string Name { get; set; }
}
class SmartList
{
private System.Collections.IList list;
public SmartList(System.Collections.IList list)
{
this.list = list;
}
public List<T> FilterPropertyType<T>(Func<T, bool> query)
{
return list.Cast<T>().Where(query).ToList();
}
}
You can use this "SmartList" in different ways (without use ParentType because is not necessary):
var stringList = new SmartList(new[] { "Rob", "Liam" });
var matches = stringList.FilterPropertyType<string>(s => s.Contains("Rob"));
Or better with classes:
var classList = new SmartList(new []{
new SmartListItem { Name = "Rob" },
new SmartListItem { Name = "Liam" }
});
var matches = classList.FilterPropertyType<SmartListItem>(smi => smi.Name.Contains("Rob"));
Using that you can avoid switch case for PropertyType and do your queries directly on the list item.

LINQ distinct with IEquatable is not returning distinct result [duplicate]

This question already has answers here:
LINQ's Distinct() on a particular property
(23 answers)
Closed 19 days ago.
class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>
{
new Book
{
Name="C# in Depth",
Authors = new List<Author>
{
new Author
{
FirstName = "Jon", LastName="Skeet"
},
new Author
{
FirstName = "Jon", LastName="Skeet"
},
}
},
new Book
{
Name="LINQ in Action",
Authors = new List<Author>
{
new Author
{
FirstName = "Fabrice", LastName="Marguerie"
},
new Author
{
FirstName = "Steve", LastName="Eichert"
},
new Author
{
FirstName = "Jim", LastName="Wooley"
},
}
},
};
var temp = books.SelectMany(book => book.Authors).Distinct();
foreach (var author in temp)
{
Console.WriteLine(author.FirstName + " " + author.LastName);
}
Console.Read();
}
}
public class Book
{
public string Name { get; set; }
public List<Author> Authors { get; set; }
}
public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override bool Equals(object obj)
{
return true;
//if (obj.GetType() != typeof(Author)) return false;
//else return ((Author)obj).FirstName == this.FirstName && ((Author)obj).FirstName == this.LastName;
}
}
This is based on an example in "LINQ in Action". Listing 4.16.
This prints Jon Skeet twice. Why? I have even tried overriding Equals method in Author class. Still Distinct does not seem to work. What am I missing?
Edit:
I have added == and != operator overload too. Still no help.
public static bool operator ==(Author a, Author b)
{
return true;
}
public static bool operator !=(Author a, Author b)
{
return false;
}
LINQ Distinct is not that smart when it comes to custom objects.
All it does is look at your list and see that it has two different objects (it doesn't care that they have the same values for the member fields).
One workaround is to implement the IEquatable interface as shown here.
If you modify your Author class like so it should work.
public class Author : IEquatable<Author>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Equals(Author other)
{
if (FirstName == other.FirstName && LastName == other.LastName)
return true;
return false;
}
public override int GetHashCode()
{
int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
int hashLastName = LastName == null ? 0 : LastName.GetHashCode();
return hashFirstName ^ hashLastName;
}
}
Try it as DotNetFiddle
The Distinct() method checks reference equality for reference types. This means it is looking for literally the same object duplicated, not different objects which contain the same values.
There is an overload which takes an IEqualityComparer, so you can specify different logic for determining whether a given object equals another.
If you want Author to normally behave like a normal object (i.e. only reference equality), but for the purposes of Distinct check equality by name values, use an IEqualityComparer. If you always want Author objects to be compared based on the name values, then override GetHashCode and Equals, or implement IEquatable.
The two members on the IEqualityComparer interface are Equals and GetHashCode. Your logic for determining whether two Author objects are equal appears to be if the First and Last name strings are the same.
public class AuthorEquals : IEqualityComparer<Author>
{
public bool Equals(Author left, Author right)
{
if((object)left == null && (object)right == null)
{
return true;
}
if((object)left == null || (object)right == null)
{
return false;
}
return left.FirstName == right.FirstName && left.LastName == right.LastName;
}
public int GetHashCode(Author author)
{
return (author.FirstName + author.LastName).GetHashCode();
}
}
Another solution without implementing IEquatable, Equals and GetHashCode is to use the LINQs GroupBy method and to select the first item from the IGrouping.
var temp = books.SelectMany(book => book.Authors)
.GroupBy (y => y.FirstName + y.LastName )
.Select (y => y.First ());
foreach (var author in temp){
Console.WriteLine(author.FirstName + " " + author.LastName);
}
There is one more way to get distinct values from list of user defined data type:
YourList.GroupBy(i => i.Id).Select(i => i.FirstOrDefault()).ToList();
Surely, it will give distinct set of data
Distinct() performs the default equality comparison on objects in the enumerable. If you have not overridden Equals() and GetHashCode(), then it uses the default implementation on object, which compares references.
The simple solution is to add a correct implementation of Equals() and GetHashCode() to all classes which participate in the object graph you are comparing (ie Book and Author).
The IEqualityComparer interface is a convenience that allows you to implement Equals() and GetHashCode() in a separate class when you don't have access to the internals of the classes you need to compare, or if you are using a different method of comparison.
You've overriden Equals(), but make sure you also override GetHashCode()
The Above answers are wrong!!!
Distinct as stated on MSDN returns the default Equator which as stated The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T
Which means as long as you overide Equals you are fine.
The reason you're code is not working is because you check firstname==lastname.
see https://msdn.microsoft.com/library/bb348436(v=vs.100).aspx and https://msdn.microsoft.com/en-us/library/ms224763(v=vs.100).aspx
You can achieve this several ways:
1. You may to implement the IEquatable interface as shown Enumerable.Distinct Method or you can see #skalb's answer at this post
2. If your object has not unique key, You can use GroupBy method for achive distinct object list, that you must group object's all properties and after select first object.
For example like as below and working for me:
var distinctList= list.GroupBy(x => new {
Name= x.Name,
Phone= x.Phone,
Email= x.Email,
Country= x.Country
}, y=> y)
.Select(x => x.First())
.ToList()
MyObject class is like as below:
public class MyClass{
public string Name{get;set;}
public string Phone{get;set;}
public string Email{get;set;}
public string Country{get;set;}
}
3. If your object's has unique key, you can only use the it in group by.
For example my object's unique key is Id.
var distinctList= list.GroupBy(x =>x.Id)
.Select(x => x.First())
.ToList()
You can use extension method on list which checks uniqueness based on computed Hash.
You can also change extension method to support IEnumerable.
Example:
public class Employee{
public string Name{get;set;}
public int Age{get;set;}
}
List<Employee> employees = new List<Employee>();
employees.Add(new Employee{Name="XYZ", Age=30});
employees.Add(new Employee{Name="XYZ", Age=30});
employees = employees.Unique(); //Gives list which contains unique objects.
Extension Method:
public static class LinqExtension
{
public static List<T> Unique<T>(this List<T> input)
{
HashSet<string> uniqueHashes = new HashSet<string>();
List<T> uniqueItems = new List<T>();
input.ForEach(x =>
{
string hashCode = ComputeHash(x);
if (uniqueHashes.Contains(hashCode))
{
return;
}
uniqueHashes.Add(hashCode);
uniqueItems.Add(x);
});
return uniqueItems;
}
private static string ComputeHash<T>(T entity)
{
System.Security.Cryptography.SHA1CryptoServiceProvider sh = new System.Security.Cryptography.SHA1CryptoServiceProvider();
string input = JsonConvert.SerializeObject(entity);
byte[] originalBytes = ASCIIEncoding.Default.GetBytes(input);
byte[] encodedBytes = sh.ComputeHash(originalBytes);
return BitConverter.ToString(encodedBytes).Replace("-", "");
}
The Equal operator in below code is incorrect.
Old
public bool Equals(Author other)
{
if (FirstName == other.FirstName && LastName == other.LastName)
return true;
return false;
}
NEW
public override bool Equals(Object obj)
{
var other = obj as Author;
if (other is null)
{
return false;
}
if (FirstName == other.FirstName && LastName == other.LastName)
return true;
return false;
}
Instead of
var temp = books.SelectMany(book => book.Authors).Distinct();
Do
var temp = books.SelectMany(book => book.Authors).DistinctBy(f => f.Property);

Linq Expression with multiple nested properties

I have read through the question, and answer, Dynamic linq expression tree with nested properties. It does seem to be very similar, though a lack of understanding with Expressions is resulting in me not being able to translate the answer to my own scenario.
Given a class structure that looks a little like this:
public class Parent
{
public Parent()
{
ParentField = new HashSet<ParentField>();
}
public int ParentId { get; set; }
public ICollection<ParentField> ParentField { get; set; }
}
public class ParentField
{
public int ParentField { get; set; }
public Field Field { get; set; }
public string Value {get;set;}
}
public class Field
{
public int FieldId { get; set; }
public string Name { get; set; }
}
I am trying to build up a query that would be represented by this:
var query = _unitOfWork.ParentRepository.Queryable().Include("ParentField.Field");
query = query.Where(i =>
(
i.ParentField.Any(pField => pField.Field.Name.Equals("anId", StringComparison.OrdinalIgnoreCase)) &&
i.ParentField.Any(pField =>
// There may be multiple values to search for, so require the OR between each value
pField.Value.Equals("10", StringComparison.OrdinalIgnoreCase) || pField.Value.Equals("20", StringComparison.OrdinalIgnoreCase))
)
// There may be multiple Names to search for, so require the AND between each Any
&&
(
i.ParentField.Any(pField => pField.Field.Name.Equals("anotherId", StringComparison.OrdinalIgnoreCase)) &&
i.ParentField.Any(pField =>
pField.Value.Equals("50", StringComparison.OrdinalIgnoreCase) || pField.Value.Equals("60", StringComparison.OrdinalIgnoreCase))
));
The important parts to note is that there can be many "Field.Name"'s to search for, as well as multiple "Values" within each of the groups.
I'm not able to give much of an example of what I have tried so far, given I am not sure where to actually start.
Any pointers would be fantastic.
In this particular case there is no need to build dynamic expression predicate. The && can be achieved by chaining multiple Where, and || by putting the values into IEnumerable<string> and using Enumerable.Contains.
For single name / values filter it would be something like this:
var name = "anId".ToLower();
var values = new List<string> { "10", "20" }.Select(v => v.ToLower());
query = query.Where(p => p.ParentField.Any(
pf => pf.Field.Name == name && values.Contains(pf.Value.ToLower())));
And for multiple key / values pairs:
var filters = new Dictionary<string, List<string>>
{
{ "anId", new List<string> { "10", "20" } },
{ "anotherId", new List<string> { "50", "60" } },
};
foreach (var entry in filters)
{
var name = entry.Key.ToLower();
var values = entry.Value.Select(v => v.ToLower());
query = query.Where(p => p.ParentField.Any(
pf => pf.Field.Name == name && values.Contains(pf.Value.ToLower())));
}
#geraphl's answer presents the same idea, but w/o taking into account EF query provider specific requirements (no dictionary methods, only primitive value list Contains, no Equals with StringComparison.OrdinalIgnoreCase usage, but == and ToLower etc.)
I am not sure but i think you are searching for something like this.
First you have to put your searched values in a data-type that is capable of doing what you want, which is in this case a dictionary:
var nameValues = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{ "anId" , new string[] {"10", "20"} },
{ "anotherId" , new string[] {"50", "60"} },
};
Then you first check if the name is in the dictionary and if so, you also check if one of the values also listed is in the list you search.
var query = _unitOfWork.ParentRepository.Queryable().Include("ParentField.Field");
query = query.Where(i =>
(
i.ParentField.Any(pFieldOuter => nameValues.ContainsKey(pFieldOuter.Field.Name) ?
i.ParentField.Any(pFieldInner => nameValues[pFieldOuter.Field.Name].Contains(pFieldInner.Value, StringComparer.OrdinalIgnoreCase))
: false
)
));
But if you want, that all your searched names and values are included you have to do this.
var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "anId", "anotherId" };
var values = new List<List<string>>() {
new List<string> { "10", "20" },
new List<string> { "50", "60" }
};
var query = _unitOfWork.ParentRepository.Queryable().Include("ParentField.Field");
query = query.Where(i =>
(
names.All(n => i.ParentField.Any(pField => pField.Name.Equals(n, StringComparison.OrdinalIgnoreCase))) &&
values.All(l => l.Any(v => i.ParentField.Any(pField => pField.Value.Equals(v, StringComparison.OrdinalIgnoreCase))))
));
Even if i am sure this is not the most effective way to do is, it may be a good hint for you.

Linq query to search

I have a collection of Employee class and employee class has few properties like departement,manager name,payscale,designation etc.Now in my webapi, i have a search method in which i am searching a string across all fields of webapi
like if I search Peter it'll search in all fields(departement,manager_name,payscale,designation) of all employees.For this i am using below:-
public IEnumerable<Employee> Search(string searchstr)
{
if (repository != null)
{
var query =
from employees in repository.GetEmployees()
where
(employees.departement != null && employees.departement.Contains(searchstr)) ||
(employees.payscale != null && employees.payscale.Contains(searchstr))
(movie.designation != null && movie.designation.Contains(searchstr)) )
select employees;
return query.AsEnumerable().OrderBy(c => c.employeeid);
}
else
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
Though i am getting desired result,i have not to use that query.Is there any other way to rewrite same query?
As stated by Noctis, using reflection results in a heavy task for the .NET runtime.
Here is some example code that loops trough all properties of a class and searchs a string concidence. It uses reflection ;)
Any questions, leave a comment asking!
The code in the entry point of the APP:
[STAThread]
private static void Main(string[] args)
{
var person1 = new Person {Name = "The first name", Address = "The first address"};
var person2 = new Person {Name = "The second name", Address = "The second address"};
var results = SearchStringTroughAllProperties("second", new List<Person> {person1, person2});
}
The Person class:
class Person
{
public string Name { get; set; }
public string Address { get; set; }
}
And the SearchStringTroughAllProperties method:
private static IEnumerable<Person> SearchStringTroughAllProperties(string stringToSearch,
IEnumerable<Person> persons)
{
var properties =
typeof (Person).GetProperties()
.Where(x => x.CanRead && x.PropertyType == typeof (string))
.Select(x => x.GetMethod)
.Where(x => !x.IsStatic)
.ToList();
return persons.Where(person =>
properties.Select(property => (string) property.Invoke(person, null) ?? string.Empty)
.Any(propertyValueInInstance => propertyValueInInstance.Contains(stringToSearch)));
}
Notice that:
It searchs in properties, not in fields
It only searchs on properties that can be read (have a get defined)
It only searchs on properties of type string
It only searchs on properties that aren't static members of the class
EDIT:
For searching the string coincidence in a string or string[] property, change SearchStringTroughAllProperties method to this (it gets longer!):
static IEnumerable<Person> SearchStringTroughAllProperties(string stringToSearch, IEnumerable<Person> persons)
{
var properties =
typeof (Person).GetProperties()
.Where(x => x.CanRead && (x.PropertyType == typeof (string) || x.PropertyType == typeof(string[])))
.Select(x => x.GetMethod)
.Where(x => !x.IsStatic)
.ToList();
foreach (var person in persons)
{
foreach (var property in properties)
{
bool yieldReturned = false;
switch (property.ReturnType.ToString())
{
case "System.String":
var propertyValueStr = (string) property.Invoke(person, null) ?? string.Empty;
if (propertyValueStr.Contains(stringToSearch))
{
yield return person;
yieldReturned = true;
}
break;
case "System.String[]":
var propertyValueStrArr = (string[]) property.Invoke(person, null);
if (propertyValueStrArr != null && propertyValueStrArr.Any(x => x.Contains(stringToSearch)))
{
yield return person;
yieldReturned = true;
}
break;
}
if (yieldReturned)
{
break;
}
}
}
}
Even though work, it feels a bit dirty. I would consider maybe using reflection to get the properties of the class, and then dynamically search them.
The benefit would be: if you add a new property tomorrow, there's nothing else you need to change.
The disadvantage would be: probably not as performant since reflection is much slower than simply searching for things you know exist.
Having said that, i'm sure there are some other nifty advanced linq tricks that maybe others can point out.
Accessing Attributes by Using Reflection (C# and Visual Basic)
I thought I have some handy code but I don't. I wouldn't like to write it of the top of my head, because it probably won't compile (you need to get the syntax right).
Have a look at the above link :)

Comparing Nested object properties using C#

I have a method which compares two objects and returns a list of all the property names which are different.
public static IList<string> GetDifferingProperties(object source, object target)
{
var sourceType = source.GetType();
var sourceProperties = sourceType.GetProperties();
var targetType = target.GetType();
var targetProperties = targetType.GetProperties();
var properties = (from s in sourceProperties
from t in targetProperties
where s.Name == t.Name &&
s.PropertyType == t.PropertyType &&
s.GetValue(source,null) != t.GetValue(target,null)
select s.Name).ToList();
return properties;
}
For example if I have two classes as follows:
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
public class Employee
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public Address EmployeeAddress { get; set; }
}
I am trying to compare the following two employee instances:
var emp1Address = new Address();
emp1Address.AddressLine1 = "Microsoft Corporation";
emp1Address.AddressLine2 = "One Microsoft Way";
emp1Address.City = "Redmond";
emp1Address.State = "WA";
emp1Address.Zip = "98052-6399";
var emp1 = new Employee();
emp1.FirstName = "Bill";
emp1.LastName = "Gates";
emp1.EmployeeAddress = emp1Address;
var emp2Address = new Address();
emp2Address.AddressLine1 = "Gates Foundation";
emp2Address.AddressLine2 = "One Microsoft Way";
emp2Address.City = "Redmond";
emp2Address.State = "WA";
emp2Address.Zip = "98052-6399";
var emp2 = new Employee();
emp2.FirstName = "Melinda";
emp2.LastName = "Gates";
emp2.EmployeeAddress = emp2Address;
So when I pass these two employee objects to my GetDifferingProperties method currently it returns FirstName and EmployeeAddress, but it does not tell me which exact property (which in this case is Address1) in the EmployeeAddress has changed. How can I tweak this method to get something like EmployeeAddress.Address1?
It's because you are using != which, for objects, tests the identity of an object rather than its value. The key is to use recursion to generate the list of properties of properties. This will go as deep as you want...
public static IList<string> GetDifferingProperties(object source, object target)
{
var sourceType = source.GetType();
var sourceProperties = sourceType.GetProperties();
var targetType = target.GetType();
var targetProperties = targetType.GetProperties();
var result = new List<string>();
foreach (var property in
(from s in sourceProperties
from t in targetProperties
where s.Name == t.Name &&
s.PropertyType == t.PropertyType &&
!Equals(s.GetValue(source, null), t.GetValue(target, null))
select new { Source = s, Target = t }))
{
// it's up to you to decide how primitive is primitive enough
if (IsPrimitive(property.Source.PropertyType))
{
result.Add(property.Source.Name);
}
else
{
foreach (var subProperty in GetDifferingProperties(
property.Source.GetValue(source, null),
property.Target.GetValue(target, null)))
{
result.Add(property.Source.Name + "." + subProperty);
}
}
}
return result;
}
private static bool IsPrimitive(Type type)
{
return type == typeof(string) || type == typeof(int);
}
I can recommend using http://comparenetobjects.codeplex.com/
This has a possibility to compare nested objects, enums, ILists, etc.
The project is free and easy to use(Just 1 .cs file). Moreover, it is possible to get the values that are different, add properties to ignore, etc.
In principle, you'll need to use the technique you implemented in GetDifferingProperties on the two objects that you want to compare after you get their values (using GetValue in the query). Probably the most straightforward implementation is to make the method recursive:
public static IEnumerable<string> GetDifferingProperties
(object source, object target) {
// Terminate recursion - equal objects don't have any differing properties
if (source == target) return new List<string>();
// Compare properties of two objects that are not equal
var sourceProperties = source.GetType().GetProperties();
var targetProperties = target.GetType().GetProperties();
return
from s in sourceProperties
from t in targetProperties
where s.Name == t.Name && s.PropertyType == t.PropertyType
let sVal = s.GetValue(source, null)
let tVal = t.GetValue(target, null)
// Instead of comparing the objects directly using '==', we run
// the method recursively. If the two objects are equal, it returns
// empty list immediately, otherwise it generates multiple properties
from name in GetDifferingProperties(sVal, tVal)
select name;
}
If you want to use this in practice, you'll probably want to keep track of how to get to the property (this code gives you just a list of property names without information about the object that contains them). You can change the last line from select name to select s.Name + "." + name which will give you a more complete name (e.g. Address.Name if the property that differs is the Name property of the Address member).
One point: Your method is not accounting for actual differences in the the EmployeeAddress properties. Test it and see.
emp2Address.AddressLine1 = emp1Address.AddressLine1;// "Gates Foundation";
emp2Address.AddressLine2 = emp1Address.AddressLine2;// "One Microsoft Way";
emp2Address.City = emp1Address.City;// "Redmond";
emp2Address.State = emp1Address.State;// "WA";
emp2Address.Zip = emp1Address.Zip;// "98052-6399";
The program will still return EmployeeAddress as a non-matching property. However, if you simply set emp2.EmployeeAddress = emp1Address, you don't get the "non-match."
Something something about references...
At any rate, if you want to find what's different about that object, you're going to have to search for what's different about that object.

Categories