0

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

Policy1

PolicyMod Yes HasSwimmingPool No

Policy2

PolicyMod No HasSwimmingPool Yes

Community
  • 1
  • 1
juleekwin
  • 521
  • 1
  • 9
  • 25
  • Could you add a DateTime `TimeStamp` to your class? Then, anytime a new record is inserted, you would use `TimeStamp=GetDate()` on the SQL. –  Jul 18 '13 at 16:14
  • @jp2code I know they're different the data came from XML files and they only create a new policy rating if something has changed. It's two sets of data for one policy. I'm creating a toll to show people why the rate changed. The goal is to just display what has changed. Like if thay added or got rid of a swimming pool. – juleekwin Jul 18 '13 at 16:18
  • The XML files should have date stamps on them. So, the older date would be the original, and the newer date would be "what changed". Are you looking for anything else? –  Jul 18 '13 at 16:25
  • possible duplicate of [Finding property differences between two C# objects](http://stackoverflow.com/questions/2387946/finding-property-differences-between-two-c-sharp-objects) – Chris Pitman Jul 18 '13 at 16:27

4 Answers4

1

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.

Community
  • 1
  • 1
Bobson
  • 13,498
  • 5
  • 55
  • 80
  • That Isn't what I'm trying to accomplish, if I did that I would know that the entire policy is different. I already know the policies differ, I want to know in which specific elements they differ. Like policy1 didn't have a swimming pool but policy2 did and then I want to print only the differences to the screen to show how they differ. – juleekwin Jul 18 '13 at 16:15
  • @juleekwin - Ah, I misunderstood. A series of `if`s is probably your best bet, then. – Bobson Jul 18 '13 at 16:47
1

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.

Zenilogix
  • 1,318
  • 1
  • 15
  • 31
0

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;
  }

}
  • The time stamping isn't what I'm looking for, it wouldn't work how my project st set up. This also is a lot more implementation compared to what I already have. Thanks for trying though. – juleekwin Jul 18 '13 at 17:32
0

After much research, I did end up using a series of if statements like I originally stated. It feels so icky though! :( Oh well!

juleekwin
  • 521
  • 1
  • 9
  • 25