Все ли приведения C # приводят к упаковке / распаковке - PullRequest
11 голосов
/ 20 февраля 2012

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

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

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

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

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

Например:

public class A
{
}

public class B : A
{
}

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

Ответы [ 3 ]

24 голосов
/ 20 февраля 2012

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

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

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

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

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

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

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

Является ли эта проверка во время выполнения "дорогой" или нет, зависит от вашего бюджета.

Можно ли измерить эту стоимость должным образом?

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

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

Какие самые дорогие преобразования?

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

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

10 голосов
/ 20 февраля 2012

номер

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

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

7 голосов
/ 20 февраля 2012

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

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

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

Краткий ответ: №

Длинный ответ: определить дорого.Тем не менее, нет.

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

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

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

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

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; // это «дорогая» операция?это не бокс

нет, это "дешево".

...