Click here to Skip to main content
15,893,487 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
Hi everyone.

C#
Object guid1 = Guid.Empty;
Object guid2 = Guid.Empty;


Why guid1 is different than guid2 ? They have the same value an empty Guid. For me it's weird. But I think there's a reason that I don't know.
(I know I can do the same different, but the question is just why this)


In case of string, they are equals as expected.
C#
Object string1 = string.Empty;
Object string2 = string.Empty;


Thanks
Posted

OK, I don't see a comprehensive Answer right now, so I need to explain everything.

Basically, when you use "==" you don't compare object by referential identity. The result depends on comparison operator defined in class.

I don't know how you get your result, but let's test is correctly:

C#
System.Guid g1 = System.Guid.Empty;
System.Guid g2 = System.Guid.Empty;
bool semanticallyEqual = g1 == g2; //true; don't say they are not, just like with strings!
bool referentiallyEqual = object.ReferenceEquals(g1, g2); //false, different objects
bool isTheSame = g1.Equals(g2); //true; 


Just to finally amaze you:
C#
string s1 = "a";
string s2 = "a";
//believe or not: will return true:
bool equalStrRef = object.ReferenceEquals(s1, s2);


The class System.String is very special, quite different from all other classes! The idea is extreme reuse of memory but exact simulation of value semantic.

Let's illustrate modification of equality rules:

C#
public class IdentitySample {

    public IdentitySample(int intValue, string stringValue) {
        this.FIntValue = intValue;
        this.FStringValue = stringValue;
    } //IdentitySample

    public int IntValue { get { return FIntValue; } }
    public string StringValue { get { return FStringValue; } }

    public override int GetHashCode() {
        return FIntValue.GetHashCode() ^ FStringValue.GetHashCode();
    } //GetHashCode

    public override bool Equals(object obj) {
        if (object.ReferenceEquals(obj, null)) return false;
        IdentitySample sameTypeObject = obj as IdentitySample;
        if (object.ReferenceEquals(sameTypeObject, null)) return false;
        return
            sameTypeObject.FIntValue == this.FIntValue &&
            sameTypeObject.FStringValue == this.FStringValue;
    } //Equals

    public static bool operator ==(IdentitySample left, IdentitySample right) {
        if (object.ReferenceEquals(left, null) && (object.ReferenceEquals(right, null)))
            return true;
        else if (object.ReferenceEquals(left, null) && (!object.ReferenceEquals(right, null)))
            return false;
        else if (!object.ReferenceEquals(left, null) && (object.ReferenceEquals(right, null)))
            return false;
        else
            return left.Equals(right);
    } //==
    public static bool operator !=(IdentitySample left, IdentitySample right) {
        return !(left == right);
    } //!=

    int FIntValue;
    string FStringValue;

} //class IdentitySample


Consider the following important items here:

In the implementation, you cannot any longer use "==" for comparison, must use object.ReferenceEquals, otherwise you can run into infinite recursion.
The syntax will not allow your to define == or !=, along, it will require that both are defined.

A very important override is object.GetHashCode. If it is not overridden, compilation would fail. Here is why: you can store the instances of your class in a container like Dictionary which uses buckets technique for structuring item data and fast search (the complexity is estimated as O(1)!). The technique is based on the hash codes. The semantically different instances should have higher probability of having different hash code. So, in your implementation of this method you should take into account semantically significant members (only). Also, using XOR operator if a very reasonable choice; it eliminated wrapping over of integers (which would take place if you would add integers) but not ignore information on differences between different values. (To understand what I mean, take two bitmaps and XOR them, then XOR two more times…)

—SA
 
Share this answer
 
v10
Comments
luisnike19 6-Apr-11 21:04pm    
Thanks for your answer SA, that makes a lot of sense. I knew you were going to post an answer for this question.
Sergey Alexandrovich Kryukov 6-Apr-11 21:09pm    
Well, thank you for accepting this Answer.
That's not all.
Do you know how to re-define Equals, "==" and "!="? That you need also to override object.GetHashCode and why? This is very important. I was about to add it.
--SA
Sergey Alexandrovich Kryukov 6-Apr-11 21:31pm    
Now, that's all about it. Good to know, I'll tell you...
--SA
luisnike19 6-Apr-11 22:53pm    
Very interesting! Thank you very much SA. I really enjoy to read your answers.
Sergey Alexandrovich Kryukov 6-Apr-11 22:59pm    
...just added a minor update.
You're very welcome!
Good luck, call again.
--SA
I assume you mean that c is false in this example:

C#
Object a = Guid.Empty;
Object b = Guid.Empty;
bool c = a == b;


But not is this:

C#
String a = String.Empty;
String b = String.Empty;
bool c = a == b;


It's because of the value semantics of the structs. Guids are structs so they're passed by value, meaning each "copy" is a new instance even if it's been assigned from a static readonly field.

To work around it, either declare them as Guid rather than Object or call the Equals method.

Hope this helps,
Fredrik Bornander
 
Share this answer
 
Comments
luisnike19 6-Apr-11 21:02pm    
Thanks for your answer.
a string with "empty" value is a empty string.

a guid type is an instance of the guid class. if you have two instances, then you have to instances in memory. the memory address (yes, basically there is a pointer to their memory address) are different. so they are different.
 
Share this answer
 
Comments
luisnike19 6-Apr-11 21:02pm    
Thanks for your answer.
They're different because you're generating two instances of the object. It's the same as doing this:

C#
Object guid1 = new Guid();
Object guid2 = new Guid();
 
Share this answer
 
Comments
luisnike19 6-Apr-11 21:02pm    
Thanks for your answer.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900