Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does casting an Object in C# always return a Reference to the initial object

Tags:

c#

casting

I'm currently doing a project in C# working with windows forms. During the course of it, I did the following

        void HideButtons(object sender, EventArgs e)
    {
        Button hider = ((Button)sender);
        foreach(Button tohide in hider.Parent.Controls)
            tohide.Hide();
        hider.Show();
        hider.Text = "UnHide";
        hider.Click -= new EventHandler(HideButtons);
        hider.Click += new EventHandler(ShowButtons); 
    }

The purpose of this code is to have a button which hides all the other buttons in the container it's in except itself, and then turn into an Unhide button which does the same thing in reverse.

Now, that's all well and good, except, as I compile this, I realize to myself I've hit a problem. hider is its unique object, being the return from ((Button)sender). It's not necessarily the reference to sender, and this code will probably do nothing.

But low and behold, it works exactly like I wanted it to and initially thought it would. Which got me to wondering, does a cast always return a reference to the original object? If not, how do I guarantee that (button)sender = sender?

I know that's not the case for doubles/ints, as

        public static int Main()
    {
        int a;
        double b;
        b = 10.5;
        a = (int)b;
        a++;
        return 0;
    }

ends up with a being 11, and b being 10.5 But that may be due to doubles/ints being structs. This behavior worries me, and it'd be nice to know that it will always return a reference so I can put my worrysome mind to rest.

like image 518
Kurisu Avatar asked Jun 30 '09 15:06

Kurisu


2 Answers

For reference types. if the cast is just up or down the inheritance hierarchy, then yes. This is a reference conversion. From the C# 3.0 language spec, section 6.2.4:

Reference conversions, implicit or explicit, never change the referential identity of the object being converted. In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

This is the case you're using in your WinForms code.

However, in other (still reference type) cases it may invoke a user-defined conversion. For example:

using System;

class Foo
{
}

class Bar
{
    public static explicit operator Bar(Foo f)
    {
        return new Bar();
    }
}

class Test
{
    static void Main()
    {
        Foo f = new Foo();
        Bar b = (Bar) f;
        Console.WriteLine(object.ReferenceEquals(f, b)); // Prints False
    }
}

User-defined conversions like this are relatively rare.

For value types, there are boxing and unboxing conversions, along with other conversions (e.g. between int and double).

like image 186
Jon Skeet Avatar answered Oct 22 '22 22:10

Jon Skeet


For reference types casted through the inheritance hierarchy, it'll always reference the same instance. However, for value types, casts might involve boxing and unboxing which will copy stuff. Other than that, casts are not just in the inheritance hierarchy. You can declare your own cast operator which has the characteristics of a method. It can return whatever object it likes.

like image 24
mmx Avatar answered Oct 22 '22 22:10

mmx