Все ли приведения C # приводят к упаковке / распаковке

Мне любопытно узнать, все ли приведения в C # приводят к боксу, а если нет, все ли приведения являются дорогостоящей операцией?

Пример взят из Упаковка и распаковка (Руководство по программированию на C #)

    int i = 123;
    // The following line boxes i.
    object o = i;  

Эта строка, очевидно, вызывает бокс (упаковка типа int как объекта). Эта операция считается дорогостоящей, поскольку создает мусор, который будет собираться.

А как насчет приведений из двух разных типов ссылочных типов? какова стоимость этого? его можно правильно измерить? (по сравнению с предыдущим примером)

Например:

public class A
{
}

public class B : A
{
}

var obj = new B();
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing

person lysergic-acid    schedule 20.02.2012    source источник
comment
При преобразовании от одного ссылочного типа к другому бокс не используется.   -  person BrokenGlass    schedule 20.02.2012
comment
Поддается ли он надлежащему измерению? следует избегать?   -  person lysergic-acid    schedule 20.02.2012
comment
Хотя при преобразовании одного ссылочного типа в другой бокс не используется, преобразование может иметь место. Преобразование одного ссылочного типа в другой несвязанный ссылочный тип может быть дорогостоящим.   -  person Matt Davis    schedule 20.02.2012
comment
возможный дубликат В чем разница между упаковкой / распаковкой и приведение типов?   -  person Henk Holterman    schedule 20.02.2012
comment
Вы должны увидеть это is-casting-to-an-interface-a- бокс-конверсия   -  person nawfal    schedule 17.12.2013


Ответы (3)


Мне любопытно узнать, все ли преобразования в C # приводят к боксу.

Нет. Только бокс-конверсии приводят к боксу, отсюда и название "бокс-конверсии". Упаковочные преобразования - это все встроенные преобразования из типов значений в ссылочные типы - либо в класс, от которого наследуется тип значения, либо в интерфейс, который он реализует. (Или к интерфейсу, совместимому с интерфейсом, который он реализует, посредством ковариантного или контравариантного преобразования ссылок.)

все ли преобразования - дорогостоящая операция?

Нет. Преобразование идентификаторов не требует затрат, потому что компилятор может их полностью исключить.

Каковы затраты на неявное и явное преобразование ссылок?

Неявные преобразования ссылок не требуют затрат. Компилятор может их полностью исключить. То есть преобразование из Giraffe в его базовый тип Animal или Giraffe в его реализованный тип интерфейса IAmATallMammal является бесплатным.

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

Будет ли эта проверка во время выполнения «дорогостоящей» или нет, зависит от вашего бюджета.

можно ли правильно измерить эту стоимость?

Конечно. Решите, какой ресурс важен для вас, скажем, время, а затем внимательно измерьте свое потребление времени с помощью секундомера.

Вопрос, который вы не задавали, но, вероятно, должны иметь:

Какие конверсии самые дорогие?

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

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

person Eric Lippert    schedule 20.02.2012
comment
Эрик, а как насчет неявного преобразования, сделанного явно программистом? Я предполагаю, что это тоже опущено компилятором. (Пример: var o = (object)"Some string"; return o.GetHashCode();) - person phoog; 21.02.2012
comment
@phoog: Верно. Для этого не нужно генерировать IL; строковая ссылка уже совместима по присваиванию с переменной. - person Eric Lippert; 21.02.2012

No.

Упаковка означает помещение значения в новый экземпляр ссылочного типа.

Стандартные преобразования между ссылочными типами не приводят к выделению памяти.
(Пользовательские преобразования могут делать что угодно)

person SLaks    schedule 20.02.2012
comment
Приведение из одного ссылочного типа не приводит к выделению памяти. Не обязательно верно. - person jason; 20.02.2012

Мне любопытно узнать, все ли приведения в C # приводят к боксу,

Нет. Упаковка - это особая операция, которая означает обработку экземпляра типа значения как экземпляра ссылочного типа. Для преобразования ссылочного типа в преобразование ссылочного типа эта концепция не играет никакой роли.

все ли слепки - дорогостоящая операция?

Краткий ответ: Нет.

Длинный ответ: определите «дорого». Но все равно нет.

А как насчет приведений из двух разных типов ссылочных типов? какова стоимость этого?

А что, если это просто преобразование производной ссылки в базовую? Это ОЧЕНЬ быстро, потому что ничего не происходит.

Другие, определяемые пользователем преобразования, могут быть «медленными» или «быстрыми».

Этот «медленный».

class A { public int Foo { get; set; } }
class B {
    public int Foo { get; set; }
    static Random rg = new Random();
    static explicit operator A(B b) {
        Thread.Sleep(rg.Next());
        return new A { Foo = b.Foo; }
    }
}

Этот «быстрый».

class A { public int Foo { get; set; } }
class B {
    public int Foo { get; set; }
    static Random rg = new Random();
    static explicit operator A(B b) {
        return new A { Foo = b.Foo; }
    }
}

var obj2 = (A)obj; // это «дорогая» операция? это не бокс

Нет, это «дешево».

person jason    schedule 20.02.2012
comment
дорогостоящая операция означает == если у меня есть алгоритм, который включает в себя цикл + приведение (без упаковки), разумнее ли спроектировать его по-другому, или это тривиальная операция, которая не считается дорогостоящей с точки зрения производительности (с точки зрения времени выполнения) - person lysergic-acid; 20.02.2012
comment
@liortal: Это зависит от обстоятельств. Если вас беспокоит производительность, измерьте ее. - person SLaks; 20.02.2012
comment
Я заинтересован в понимании того, как это работает, больше, чем конкретно о снижении производительности. - person lysergic-acid; 20.02.2012