Всегда ли приведение объекта в С# возвращает ссылку на исходный объект

В настоящее время я делаю проект на С#, работая с формами Windows. В процессе я сделал следующее

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

Цель этого кода состоит в том, чтобы иметь кнопку, которая скрывает все другие кнопки в контейнере, в котором она находится, кроме самой себя, а затем превращается в кнопку «Показать», которая делает то же самое в обратном порядке.

Теперь все хорошо, за исключением того, что, когда я компилирую это, я понимаю, что столкнулся с проблемой. hider — его уникальный объект, возвращаемый отправителем ((Button)). Это не обязательно ссылка на отправителя, и этот код, вероятно, ничего не сделает.

Но вот, он работает именно так, как я хотел и изначально думал, что так и будет. Что заставило меня задуматься, всегда ли приведение возвращает ссылку на исходный объект? Если нет, как я могу гарантировать, что (кнопка) отправитель = отправитель?

Я знаю, что это не относится к двойным/целым числам, так как

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

заканчивается тем, что a равно 11, а b равно 10,5. Но это может быть связано с тем, что double/ints являются структурами. Такое поведение беспокоит меня, и было бы неплохо знать, что оно всегда будет возвращать ссылку, чтобы я мог успокоиться.


person Kurisu    schedule 30.06.2009    source источник
comment
Отличный вопрос. Вот несколько заметок о том, когда актерский состав меняет представление по сравнению с сохранением идентичности. Это может быть довольно запутанным. blogs.msdn.com/ericlippert/archive/ 19.03.2009/   -  person Eric Lippert    schedule 30.06.2009


Ответы (2)


Для ссылочных типов. если приведение просто вверх или вниз по иерархии наследования, то да. Это эталонное преобразование. Из спецификации языка С# 3.0, раздел 6.2.4:

Преобразования ссылок, неявные или явные, никогда не изменяют ссылочную идентичность преобразуемого объекта. Другими словами, хотя преобразование ссылки может изменить тип ссылки, оно никогда не изменяет тип или значение объекта, на который делается ссылка.

Это случай, который вы используете в своем коде WinForms.

Однако в других (все еще ссылочных) случаях он может вызывать определяемое пользователем преобразование. Например:

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

Определяемые пользователем конверсии, подобные этой, относительно редки.

Для типов значений существуют преобразования упаковки и распаковки, а также другие преобразования (например, между int и double).

person Jon Skeet    schedule 30.06.2009

Для ссылочных типов, переданных через иерархию наследования, он всегда будет ссылаться на один и тот же экземпляр. Однако для типов значений приведения могут включать упаковку и распаковку, которые будут копировать материал. Помимо этого, приведения не только в иерархии наследования. Вы можете объявить свой собственный оператор приведения, который имеет характеристики метода. Он может вернуть любой объект, который ему нравится.

person mmx    schedule 30.06.2009
comment
Я новичок в С#. Есть ли способ узнать, является ли переданный объект value_type или reference_type? - person Naveen; 30.06.2009