Reputation: 531
I pretty much asked this question yesterday, but i'm going to reform it as a new question and be more specific.
Here is the question I asked yesterday.
I have a list of a class type (ex. ESHClass)
List<ESHClass> eshlist;
And ESHClass is composed of elements like:
public class ESHClass{
public string PolicyNumber;
public string PolicyMod;
public string MultiPolicy;
public string HasSwimmingPool;
};
So say eshlist has to policies(ESHClass) and there values equal:
eshlist[0].PolicyNumber= "7";
eshlist[0].PolicyMod= "00";
eshlist[0].MultiPolicy= "Yes";
eshlist[0].HasSwimmingPool= "No";
eshlist[1].PolicyNumber= "7";
eshlist[1].PolicyMod= "00";
eshlist[1].MultiPolicy= "No";
eshlist[0].HasSwimmingPool= "Yes";
So I have two instances of my ESHClass that the data has been set and they are being stored in eshlist
.
The next part is where my other post got warry. I want to compare the objects like:
eshlist[0].PolicyNumber == eshlist[1].PolicyNumber //I know this isn't correct code its
//just to show how I would compare.
eshlist[0].HasSwimmingPool == eshlist[1].HasSwimmingPool
and then if the two objects i'm comparing are different I want to keep them in a list to print them on my webpage which I made with MVC 4 and the page is a ListView.
My post from yesterday was asking more about doing this in the most efficient way...today I got to thinking about it and idk if i'll really be able to get away from doing it for each element... right now this is now i'm doing it:
public List<ESHList> Compare(List<ESHClass> polList)
{
var l = polList;
if (l[0].PolicyNumber.Equals(l[1].PolicyNumber))
l[0].PolicyNumber = l[1].PolicyNumber = null;
if (l[0].HasSwimmingPool.Equals(l[1].HasSwimmingPool))
l[0].HasSwimmingPool = l[1].HasSwimmingPool= null;
}
So all the equal elements are nulled out and only the different elements are returned in the list. This is where i'm calling the Compare method:
Index.cshtml:
{
...
return View((esh.Compare(eshList)).DefaultIfEmpty());
}
So now after showing a more detailed explanation do you think there's a way to get away from a long series of ifs or just a better way to do what i'm trying today yet keep the result in a list I can print on the screen? As I said in my other post i'm newer to C# and completely new to web programming. If you have any helpful answers or articles I could reference, please let me know! Thank you!
EDIT: Just to show using my example what my screen will show
PolicyMod Yes HasSwimmingPool No
PolicyMod No HasSwimmingPool Yes
Upvotes: 0
Views: 220
Reputation: 531
After much research, I did end up using a series of if statements like I originally stated. It feels so icky though! :( Oh well!
Upvotes: 0
Reputation:
A good start would be to modify your ESHClass
to implement IComparable:
public class ESHClass : IComparable<ESHClass> {
public ESHClass() {
TimeStamp = DateTime.MinValue;
}
public string PolicyNumber { get; set; }
public string PolicyMod { get; set; }
public string MultiPolicy { get; set; }
public string HasSwimmingPool { get; set; }
public DateTime TimeStamp { get; set; }
public int CompareTo(ESHClass other) {
int value = PolicyNumber.CompareTo(other.PolicyNumber);
if (value == 0) {
value = TimeStamp.CompareTo(other.TimeStamp);
}
return value;
}
public override string ToString() {
return PolicyNumber;
}
}
Now, to give that class some Horsepower, you could modify it to include a couple of const
fields that should be set for your program and a static
method to do all of the work:
private const string DEFAULT_FOLDER = @"C:\TEMP";
private const string FILE_EXTENSION = "*.xml";
public static ICollection<ESHClass> SortedPolicies() {
var list = new List<ESHClass>();
var dir = new DirectoryInfo(DEFAULT_FOLDER);
foreach (var file in dir.GetFiles(FILE_EXTENSION)) {
using (var xmlReader = System.Xml.XmlReader.Create(file.FullName)) {
var esh = new ESHClass() { TimeStamp = file.CreationTime };
try {
while (xmlReader.Read()) {
if (xmlReader.IsStartElement()) {
switch (xmlReader.Name) {
case "PolicyNumber":
esh.PolicyNumber = xmlReader.Value;
break;
case "PolicyMod":
esh.PolicyMod = xmlReader.Value;
break;
case "MultiPolicy":
esh.MultiPolicy = xmlReader.Value;
break;
case "HasSwimmingPool":
esh.HasSwimmingPool = xmlReader.Value;
break;
}
}
}
list.Add(esh);
} catch (Exception err) {
throw err;
} finally {
xmlReader.Close();
}
}
}
list.Sort();
return list;
}
You would need to modify that, of course, to match your XML structure!
This could be the complete class, all fused together:
public class ESHClass : IComparable<ESHClass> {
private const string DEFAULT_FOLDER = @"C:\TEMP";
private const string FILE_EXTENSION = "*.xml";
public ESHClass() {
TimeStamp = DateTime.MinValue;
}
public string PolicyNumber { get; set; }
public string PolicyMod { get; set; }
public string MultiPolicy { get; set; }
public string HasSwimmingPool { get; set; }
public DateTime TimeStamp { get; set; }
public int CompareTo(ESHClass other) {
int value = PolicyNumber.CompareTo(other.PolicyNumber);
if (value == 0) {
value = TimeStamp.CompareTo(other.TimeStamp);
}
return value;
}
public override string ToString() {
return PolicyNumber;
}
public static ICollection<ESHClass> SortedPolicies() {
var list = new List<ESHClass>();
var dir = new DirectoryInfo(DEFAULT_FOLDER);
foreach (var file in dir.GetFiles(FILE_EXTENSION)) {
using (var xmlReader = System.Xml.XmlReader.Create(file.FullName)) {
var esh = new ESHClass() { TimeStamp = file.CreationTime };
try {
while (xmlReader.Read()) {
if (xmlReader.IsStartElement()) {
switch (xmlReader.Name) {
case "PolicyNumber":
esh.PolicyNumber = xmlReader.Value;
break;
case "PolicyMod":
esh.PolicyMod = xmlReader.Value;
break;
case "MultiPolicy":
esh.MultiPolicy = xmlReader.Value;
break;
case "HasSwimmingPool":
esh.HasSwimmingPool = xmlReader.Value;
break;
}
}
}
list.Add(esh);
} catch (Exception err) {
throw err;
} finally {
xmlReader.Close();
}
}
}
list.Sort();
return list;
}
}
Upvotes: 0
Reputation: 1403
I don't think you can get away from "a long series of ifs" when you want to properly compare two instances of a complex object (as you might implement in an overload of Equals). But, bear the following in mind:
A logical expression in C# (such as the condition of an if statement) does not perform unnecessary evaluations i.e. it stops its evaluation as soon as it determines a result.
For example:
if (a && b && c) // won't evaluate b or c if a is false, won't evaluate c if b is false
Or:
if (a || b || c) // won't evaluate b or c if a is true, won't evaluate c if b is true
So, you could write a memberwise comparison as one big expression something like:
return ((this.a == that.a) && (this.b == that.b) && (this.c == that.c) /*... etc */);
...and you'd be sure that most of the comparisons won't even be performed if the first term is false.
Perhaps this will give you some guidance toward the appropriate solution.
Upvotes: 1
Reputation: 13706
The best way to do this is to make ESHClass
know how to compare itself for equality.
See this link for a fairly in-depth example, or this question for a more minimal set.
Basically, you give the code enough information to be able to evaluate eshlist[0] == eshlist[1]
directly.
Upvotes: 1