simple string compare not so simple

I am doing jsut a simple little string compare and the values are equal, however, I cannot get them to see that they are equal. Unless I am so Dyslexic I cannot read two simple strings.

Here is the code:

public bool test_ArPermHasPermission(string prefix, string action)

{

string permission = prefix + action;

bool test = false;

foreach (string p in arPerm)

{

//the values that fail: p = auth_update and permission = auth_update

if (String.Equals(p.ToString(), permission.ToString()))

{

return true;

}

}

return false;

}

I got so fed up with the string.equals I also tried the following:

(p.ToString() == permission.ToString());

(p == permission.ToString());

(p.ToString() == permission);

(p == permission);

(String.Equals(p.ToString(), permission.ToString()));

(String.Equals(p.ToString(), permission));

(String.Equals(p, permission.ToString()));

(String.Equals(p, permission));

(p.ToString().CompareTo(permission.ToString()) == 0);

(p.ToString().CompareTo(permission.ToString()) == 0);

(p.CompareTo(permission.ToString()) == 0);

(p.ToString().CompareTo(permission) == 0);

(p.CompareTo(permission) == 0);

 

When this didn't work I removed the underscore to make the value one word.



Answer this question

simple string compare not so simple

  • chris_nelson

    Nice example of using the predicate!


  • Gurpreet Singh Sawhney

    I did have to make one modification, putting a trim on p.

    No. p is an item from the array. It should not need to be trimmed every time you do the test. It should not have extra spaces to start with, but even if it does, it should be trimmed when it is first placed in the array.



  • CruzPedro

    You know, if all those methods are failing, it's usually a sign that the strings may not be totally equal.

    If you need a case-insensitive compare, try "string.Compare(s1, s2, true) == 0"
    Or if you want to be fancy about it "s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase)"
    It's probably safe to leave out the "ToString()" call on your string (believe it or not).

    And for some unsolicited advice: You may want to reconsider doing a linear search through your string collection if it's big at all. You will probably see better performance using a binary search on a sorted array.


  • Nelis Bijl

    In the case of...what exactly are the strings in question Could case be getting in the way Here is a test I did:


    public static void TestEquality()
    {
    string one = "This is radio clash";
    string two = "This is radio clash";
    string three = "This is Radio clash";

    if (one == two) // True
        Console.WriteLine("1 == 2");

    if (one.Equals(two)) // True
        Console.WriteLine("1 Equals 2");

    if (one == three) // False
       Console.WriteLine("1 == 3");

    if (one.Equals(three)) // false
        Console.WriteLine("1 Equals 3");

    if (one.Equals(three, StringComparison.InvariantCultureIgnoreCase))
        Console.WriteLine("1 Equals (Ignore) 3"); // True

    }

     


    The comments show if they came out true or false...


  • Bill Baker

    Why do things the easy way

    THanks for the help. I have implemented this instead of my 12 line loop. I did have to make one modification, putting a trim on p.

    string permission = (prefix + action).Trim().ToLower();

    return Array.Exists(arPerm, delegate(string p) { return p.Trim() == permission; });


  • Alan M.

    right, that was a typo I made when posting the script.
  • Aleniko29139

    Trimming both operands and doing case-insensitive compare every time through the loop is a bit of a waste, when one side, presumably (arPerm) is a fixed array that you have total control over. And doing a manual search when there are built in method to do it is also a waste. The method can be reduced to :

    string[] arPerm = new string[] { "auth_update", "auth_delete" };
    public bool test_ArPermHasPermission(string prefix, string action)
    {
       string permission = (prefix + action).Trim().ToLower();
       return Array.Exists(arPerm, delegate(string p) { return p == permission; });
    }

    Now, if you don't have complete control over arPerm...It's not defined as a fixed array as above, but instead, say, read from a database, then the Trim() and ToLower() would need to be done on the string, but they should be done as teh string are loaded into the array.



  • DPotages

    I see in your example the two string are intended to be:

    //the values that fail: p = auth_update and permission = auth_update

    I also see that you create permission in this line:

    string permission = prefix + action;

    I didn't find a way to make this fail when the strings were textually equivalent, but I wonder if in your assignment to permission you neglected to include a "_" in the combination   Should the line actually be:

    string permission = prefix + "_" + action;

    If that isn't the problem, have you inspected the values of the strings in the debugger  

    If none this helps then can you post a complete minimal example of how you get this problem, for example I tried to reconstruct what you were doing as minimally and closely as I could:

    static void Main(string[] args)
      {
       string[] arPerm = new string[] { "auth_update", "auth_delete" };
       string prefix = "auth_";
       string action = "update";

       string permission = prefix + action;

       Console.WriteLine("Using String.Equals(p.ToString(), permission.ToString()))");
       foreach (string p in arPerm)
       {
        Console.Write("For entry \"" + p + "\" the comparison is ");
        if (String.Equals(p.ToString(), permission.ToString()))
        {
         Console.WriteLine("TRUE");
        }
        else
        {
         Console.WriteLine("FALSE");
        }
       }

       Console.WriteLine(Environment.NewLine + "Using: if (String.Equals(p, permission))");
       foreach (string p in arPerm)
       {
        Console.Write("For entry \"" + p + "\" the comparison is ");
        if (String.Equals(p, permission))
        {
         Console.WriteLine("TRUE");
        }
        else
        {
         Console.WriteLine("FALSE");
        }
       }

       Console.WriteLine(Environment.NewLine + "Using: if (p == permission)");
       foreach (string p in arPerm)
       {
        Console.Write("For entry \"" + p + "\" the comparison is ");
        if (p == permission)
        {
         Console.WriteLine("TRUE");
        }
        else
        {
         Console.WriteLine("FALSE");
        }
       }
      }

    The output of this program was:

    Using String.Equals(p.ToString(), permission.ToString()))
    For entry "auth_update" the comparison is TRUE
    For entry "auth_delete" the comparison is FALSE

    Using: if (String.Equals(p, permission))
    For entry "auth_update" the comparison is TRUE
    For entry "auth_delete" the comparison is FALSE

    Using: if (p == permission)
    For entry "auth_update" the comparison is TRUE
    For entry "auth_delete" the comparison is FALSE

    HTH,

    Todd


  • Henrik F Nielsen

    Also sometimes doing a .Trim() on both of them before hand is a good idea....I would recommend putting a break point at the comparision and seeing what's really what....


  • swathi_challa

    All,

    Thanks so much for the quick feedback. Trim function did the trick. The test is now:

    p.Trim().Equals(permission.Trim(), StringComparison.InvariantCultureIgnoreCase) and it works.

    Thanks again.


  • simple string compare not so simple