Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: KurisuОтветов: 2

В настоящее время я делаю проект на С#, работая с формами 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 являются структурами. Такое поведение беспокоит меня, и было бы неплохо знать, что оно всегда будет возвращать ссылку, чтобы я мог успокоиться.

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

casting

Ответы

Ответ 1 · рейтинг 18 · Jon Skeet

Для ссылочных типов. если приведение просто вверх или вниз по иерархии наследования, то да. Это эталонное преобразование. Из спецификации языка С# 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).

Ответ 2 · рейтинг 12 · mmx

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы