Почему я не могу использовать как ключевое слово для структуры?

StackOverflow https://stackoverflow.com/questions/4401344

Вопрос

Я определил следующую структуру:

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

Позже я назначаю его свойство тега другого объекта:

line.Tag = new Call(sf1, sf2);

Но когда я пытаюсь получить свойство тега, как так,

Call call = line.Tag as Call;

Visual Studio дает следующую ошибку времени компиляции:

Оператор как должен использоваться в пределах ссылочного типа или Nullable Type

Что это значит? И как я могу решить это?

Это было полезно?

Решение

Структура - это тип значения, поэтому его нельзя использовать с as оператор. То as Оператор должен иметь возможность присвоить значение NULL, если отказ от него. Это возможно только со ссылочным типом или нулевым типом значения.

Есть пара пары, чтобы решить это, но ваша лучшая ставка - это изменить Call Тип из структуры в класс. Это будет по существу изменить ваш тип из типа значений в ссылочный тип, который позволяет as Оператор для назначения значения NULL, если отказ от сбоев.

Для получения дополнительной информации о типах значений по сравнению с типовыми типами, это это приличная статья. Кроме того, посмотрите на MSDN:

Другие советы

Некоторые из существующих ответов не довольно правильно. Вы не можете использовать ненужные Типы с as, потому что результат as Является ли нулевое значение типа, если первый операнд на самом деле не соответствующий типом.

Тем не менее, вы могу использовать as С типовыми видами ... если они сочтены:

int a = 10;
object o = a;

int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value

Так что вы мог использовать:

Call? call = line.Tag as Call?;

Тогда вы можете использовать его как:

if (call != null)
{
    // Do stuff with call.Value
}

Две оговорки, хотя:

  • По моему опыту это медленнее, чем просто использовать is сопровождаемый актером
  • Вы должны серьезно пересмотреть свой нынешний Call тип:
    • Это подвергают публичные поля, которые, как правило, плохая инкапсуляция
    • Это сметный тип ценностей, который почти наверняка ошибка

Я настоятельно рекомендую вам сделать это классом вместо этого - в какой момент эта проблема уходит в любом случае.

Еще одна мысль: если тег должен всегда быть а Call, Тогда лучше бросить это:

Call call = (Call) line.Tag;

Таким образом, если данные не соответствуют вашим ожиданию (то есть есть некоторая ошибка такая, что Tag не а Call) Затем вы узнаете об этом рано, а не после того, как вы потенциально сделали другие работы. Обратите внимание, что этот актерь будет вести себя по-разному в зависимости от того, Call это структура или класс, если Tag IS NULL - вы можете отбрасывать нулевое значение для переменной типа ссылочного типа (или ненужного типа значения), но не к ненулируемому типу значения.

Из спецификации C #

§7.10.11 А в качестве оператора используется для явного преобразования значения для данного Тип ссылки или Nulleable тип. Отказ В отличие от литой выражения (§ 7.7.6), как оператор никогда не бросает исключение. Вместо этого, если указанное преобразование невозможно, полученное значение нулевой.

Ссылки и ненужные типы могут быть нулевыми. Функции - это типы ценностей, поэтому они не могут быть нулевыми.

Call? call = line.Tag as Call?;

Это ограничение C #. Если тип был ссылочным типом, то, если укомплектую не ударуется, это просто вернется «NULL», но поскольку это тип значения, он не знает, что вернется, когда отличается отключением.

Вы должны заменить ваше использование как с двумя: «это» и «как»

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}

Как указано значение, как указано, структуры являются типов ценностей.

Как я могу решить это - изменить его на

Call call = line.Tag;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top