Приведение из «System.Int16» к типу «System.Int32»

Я столкнулся с ошибкой: «Невозможно привести объект типа «System.Int16» к типу «System.Int32». Не слишком ли это нелогично? Почему? Когда я пробую следующее в непосредственных окнах, результат такой:

reader.GetInt16(mycolumn_ordinal_value)
999
reader.GetInt32(mycolumn_ordinal_value)
Exception thrown: 'System.InvalidCastException' in Microsoft.Data.SqlClient.dll

На уровне БД (sqlserver) он определяется как mycolumn smallint.

Когда я спрашиваю об этом Github Copilot, он буквально говорит:

Однако, когда вы пытаетесь использовать reader.GetInt32(mycolumn), выдается сообщение System.InvalidCastException. Это необычно (вы не можете быть серьезным, чувак!!), потому что GetInt32 должен иметь возможность обрабатывать любое значение, которое может обрабатывать GetInt16, поскольку диапазон 32-битного целого числа (от -2,147,483,648 до 2,147,483,647) равен намного больше.

Я этого не понимаю. Есть идеи?

Я готов поспорить, что это не имеет ничего общего с кастингом, а связано только с боксом. Хотя неявное приведение от int16 к int32 доступно, вы не можете распаковать int16 к int32.

Zohar Peled 28.05.2024 11:04

Логично, если поле имеет другой тип или вы пытаетесь сохранить значение в поле неправильного типа. Мы не можем гадать. Вместо случайно сгенерированных ответов публикуйте свой собственный код, запрос, схему таблицы и фактический полный текст исключения, а не только сообщение.

Panagiotis Kanavos 28.05.2024 11:04

Предполагая, что это SqlDataReader, такое поведение задокументировано в разделе «Примечания» — «Преобразования не выполняются; следовательно, полученные данные уже должны быть 32-битным целым числом со знаком».

Sweeper 28.05.2024 11:06

Генераторы случайного текста ничего не знают ни об ADO.NET, ни о чем-либо еще. Они знают только о статистике словосочетаний. Они даже не придадут большего значения документации или реализации ADO.NET. Они будут придавать такой же вес копипасте или другим случайно сгенерированным плохим статьям, например тем, которые можно найти на… определенных сайтах.

Panagiotis Kanavos 28.05.2024 11:08

Что слева? Вы присваиваете результат вызова int, long или чему-то еще?

John Wu 28.05.2024 11:08

Это происходит потому, что когда вы вызываете SqlDataReader.GetInt32() для short, он в конечном итоге вызывает внутренний код, например return (Int32)this.Value, где this.Value — это упакованный short, и именно здесь возникает исключение.

Matthew Watson 28.05.2024 11:34

@MatthewWatson, не могли бы вы написать ответ, я хочу его принять. Я попробовал смоделировать это, как вы говорите var a = (Int32)(object)(short)5;

Soner from The Ottoman Empire 28.05.2024 11:40

@PanagiotisKanavos это не имеет ничего общего с каким-либо ORM.

Soner from The Ottoman Empire 28.05.2024 11:52

@SonerfromTheOttomanEmpire Я ничего не говорил об ORM. ADO.NET — это библиотека доступа к данным .NET. SqlDataReader является частью ADO.NET, фактически до недавнего времени он был упакован в саму среду выполнения. Лишь недавно он был извлечен в библиотеку Microsoft.Data.SqlClient.

Panagiotis Kanavos 28.05.2024 11:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
228
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это происходит потому, что когда вы вызываете SqlDataReader.GetInt32() для короткого замыкания, он в конечном итоге вызывает внутренний код, например return (Int32)this.Value, где this.Value — это короткое замыкание в штучной упаковке, и именно здесь возникает исключение.

Мы можем посмотреть исходный код SqlDataReader.GetInt32():

override public Int32 GetInt32(int i) {
    ReadColumn(i);
    return _data[i].Int32;
}

Это _data массив типа SqlBuffer. Определение SqlBuffer.Int32 следующее:

internal Int32 Int32 {
    get {
        ThrowIfNull();

        if (StorageType.Int32 == _type) {
            return _value._int32;
        }
        return (Int32)this.Value; // anything else we haven't thought of goes through boxing.
    }
}

Здесь важно то, что, поскольку тип хранилища не совпадает, оно возвращает (Int32)this.Value. В данном случае this.Value имеет тип объекта и на самом деле является коробочной версией этого фактического базового типа — в вашем примере это Int16.

Следовательно, он пытается привести упакованный Int16 к Int32 и выдает исключение.

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