Операторы тестирования типов и выражения приведения — is , as typeof и приведения
Эти операторы и выражения выполняют проверку или преобразование типов. Оператор is проверяет, совместим ли тип времени выполнения выражения с заданным типом. Оператор as явно преобразует выражение в заданный тип, если его тип времени выполнения совместим с этим типом. Выражения приведения выполняют явное преобразование в целевой тип. Оператор typeof получает System.Type экземпляр для типа.
Оператор is
Оператор is проверяет, совместим ли тип среды выполнения результата определенного выражения с указанным типом. Оператор is также проверяет результат выражения на соответствие шаблону.
Выражение с оператором проверки типа is имеет следующий вид:
E is T
где E представляет выражение, возвращающее значение, а T содержит имя или параметр типа. E не может использоваться как анонимный метод или лямбда-выражение.
Оператор is возвращает true , если результат выражения имеет значение, отличное от NULL, и выполняется любое из следующих условий.
- Тип результата выражения в среде выполнения — T .
- Тип результата выражения в среде выполнения является производным от типа T , реализует интерфейс T или существует другое неявное преобразования ссылок из него в T .
- Тип результата выражения в среде выполнения является типом, допускающим значение NULL, имеющим базовый тип T , а Nullable.HasValue — true .
- Существует упаковка-преобразование или распаковка-преобразование из типа результата выражения в среде выполнения в тип T .
Оператор is не учитывает заданные пользователем преобразования.
В следующем примере показано, что оператор is возвращает true , если тип результата выражения в среде выполнения является производным от указанного типа, то есть между этими типами существует преобразование ссылки:
public class Base < >public class Derived : Base < >public static class IsOperatorExample < public static void Main() < object b = new Base(); Console.WriteLine(b is Base); // output: True Console.WriteLine(b is Derived); // output: False object d = new Derived(); Console.WriteLine(d is Base); // output: True Console.WriteLine(d is Derived); // output: True >>
В следующем примере показано, что оператор is учитывает упаковку-преобразование и распаковку-преобразование, но не учитывает числовые преобразования:
int i = 27; Console.WriteLine(i is System.IFormattable); // output: True object iBoxed = i; Console.WriteLine(iBoxed is int); // output: True Console.WriteLine(iBoxed is long); // output: False
Дополнительные сведения о преобразованиях в C# см. в главе о преобразованиях в спецификации по языку C#.
Тестирование типов с сопоставлением шаблонов
Оператор is также проверяет результат выражения на соответствие шаблону. В следующем примере показано, как использовать шаблон объявления для проверки типа выражения в среде выполнения:
int i = 23; object iBoxed = i; int? jNullable = 7; if (iBoxed is int a && jNullable is int b) < Console.WriteLine(a + b); // output 30 >
Дополнительные сведения о поддерживаемых шаблонах см. в разделе Шаблоны.
Оператор as
Оператор as явным образом преобразует результат выражения в указанный ссылочный или поддерживающий значения NULL тип. Если такое преобразование невозможно, оператор as возвращает значение null . В отличие от выражения приведения, оператор as никогда не создает исключение.
Выражение имеет такой формат:
E as T
где E представляет выражение, возвращающее значение, а T содержит имя или параметр типа. Результат такого выражения аналогичен результату этого:
E is T ? (T)(E) : (T)null
за исключением того, что E вычисляется только один раз.
Оператор as рассматривает только преобразование ссылки, допускающие значение NULL преобразования, упаковку-преобразование и распаковку-преобразование. Оператор as нельзя использовать для определенного пользователем преобразования. Для этого используйте выражение приведения.
В следующем примере иллюстрируется использование оператора as .
IEnumerable numbers = [10, 20, 30]; IList indexable = numbers as IList; if (indexable != null) < Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // output: 40 >
Как показано в примере выше, нужно сравнить результат выражения as со значением null , чтобы проверить, успешно ли выполнено преобразование. Оператор is можно использовать как для проверки успешности преобразования, так и для назначения результата новой переменной.
Выражение приведения
Выражение приведения в формате (T)E выполняет явное преобразование значения выражения E в тип T . Если явного преобразования из типа E в тип T не существует, возникает ошибка времени компиляции. Во время выполнения явное преобразование может завершиться сбоем, и выражение приведения может вызвать исключение.
Приведенный ниже пример демонстрирует явное числовое преобразование и преобразование ссылки:
double x = 1234.7; int a = (int)x; Console.WriteLine(a); // output: 1234 int[] ints = [10, 20, 30]; IEnumerable numbers = ints; IList list = (IList)numbers; Console.WriteLine(list.Count); // output: 3 Console.WriteLine(list[1]); // output: 20
Сведения о поддерживаемых явных преобразованиях см. в разделе о явных преобразованиях в спецификации по языку C#. Сведения о том, как определять пользовательские операторы явного или неявного преобразования, см. в разделе Операторы пользовательского преобразования.
Другие данные об использовании ()
Кроме того, с помощью круглых скобок можно настраивать порядок выполнения операций в выражении. Дополнительные сведения см. в разделе Операторы C#.
typeof — оператор
Оператор typeof получает экземпляр System.Type для указанного типа. Оператор typeof принимает в качестве аргумента имя типа или параметр типа, как показано в следующем примере:
void PrintType() => Console.WriteLine(typeof(T)); Console.WriteLine(typeof(List)); PrintType(); PrintType(); PrintType>(); // Output: // System.Collections.Generic.List`1[System.String] // System.Int32 // System.Int32 // System.Collections.Generic.Dictionary`2[System.Int32,System.Char]
Аргумент не должны должен быть типом, требующим заметок к метаданным. Далее приведены примеры типов.
- dynamic
- string? (или любой ссылочный тип, допускающий значение NULL)
Эти типы не представлены непосредственно в метаданных. Типы включают в себя атрибуты, описывающие базовый тип. В обоих случаях можно использовать базовый тип. Вместо dynamic можно использовать object . Вместо string? можно использовать string .
Кроме того, оператор typeof можно использовать с несвязанными универсальными типами. В имени несвязанного универсального типа должно содержаться правильное количество запятых, то есть на одну меньше, чем число параметров этого типа. В следующем примере показано использование оператора typeof с несвязанным универсальным типом:
Console.WriteLine(typeof(Dictionary)); // Output: // System.Collections.Generic.Dictionary`2[TKey,TValue]
Оператор typeof не может принимать выражение в качестве аргумента. Чтобы получить экземпляр System.Type для типа среды выполнения результата выражения, используйте метод Object.GetType.
Тестирование типов с оператором typeof
Используйте оператор typeof , чтобы проверить совместимость типа среды выполнения результата выражения с указанным типом. В следующем примере показано различие между проверкой типов, выполненной с помощью оператора typeof и оператора is:
public class Animal < >public class Giraffe : Animal < >public static class TypeOfExample < public static void Main() < object b = new Giraffe(); Console.WriteLine(b is Animal); // output: True Console.WriteLine(b.GetType() == typeof(Animal)); // output: False Console.WriteLine(b is Giraffe); // output: True Console.WriteLine(b.GetType() == typeof(Giraffe)); // output: True >>
Возможность перегрузки оператора
Операторы is , as и typeof нельзя перегружать.
Определяемый пользователем тип нельзя использовать для перегрузки оператора () , но на его основе можно определить пользовательские преобразования типа и выполнить их с помощью выражения приведения. Дополнительные сведения см. в разделе Операторы пользовательского преобразования.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
См. также
- справочник по C#
- Операторы и выражения C#
- Практическое руководство. Безопасное приведение с помощью сопоставления шаблонов, а также операторов is и as
- Универсальные шаблоны в .NET
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
typeof
Оператор typeof возвращает строку, указывающую тип операнда.
Интерактивный пример
Синтаксис
Операнд следует за оператором typeof :
typeof operand
Параметры
operand является выражением, представляющим объект или примитив, тип которого должен быть возвращён.
Описание
В следующей таблице приведены возможные возвращаемые значения typeof . Дополнительная информация о типах и примитивах находится на странице структуры данных JavaScript.
| Type | Result |
|---|---|
| Undefined | «undefined» |
| Null | «object» (смотрите ниже) |
| Boolean | «boolean» |
| Number | «number» |
| String | «string» |
| Symbol (новый тип из ECMAScript 2015) | «symbol» |
| Host object (определено JS окружением) | Зависит от реализации |
| Function object (реализует [[Call]] в терминах ECMA-262) | «function» |
| Любой другой тип | «object» |
Примеры
// Числа typeof 37 === "number"; typeof 3.14 === "number"; typeof 42 === "number"; typeof Math.LN2 === "number"; typeof Infinity === "number"; typeof NaN === "number"; // несмотря на то, что это "Not-A-Number" (не число) typeof Number(1) === "number"; // никогда не используйте эту запись! // Строки typeof "" === "string"; typeof "bla" === "string"; typeof "1" === "string"; // обратите внимание, что число внутри строки всё равно имеет тип строки typeof typeof 1 === "string"; // typeof всегда вернёт в этом случае строку typeof String("abc") === "string"; // никогда не используйте эту запись! // Booleans typeof true === "boolean"; typeof false === "boolean"; typeof Boolean(true) === "boolean"; // никогда не используйте эту запись! // Символы typeof Symbol() === "symbol"; typeof Symbol("foo") === "symbol"; typeof Symbol.iterator === "symbol"; // Undefined typeof undefined === "undefined"; typeof declaredButUndefinedVariable === "undefined"; typeof undeclaredVariable === "undefined"; // Объекты typeof a: 1 > === "object"; // используйте Array.isArray или Object.prototype.toString.call // чтобы различить обычные объекты и массивы typeof [1, 2, 4] === "object"; typeof new Date() === "object"; // То что ниже приводит к ошибкам и проблемам. Не используйте! typeof new Boolean(true) === "object"; typeof new Number(1) === "object"; typeof new String("abc") === "object"; // Функции typeof function () > === "function"; typeof class C > === "function"; typeof Math.sin === "function";
null
// Это было определено с рождения JavaScript typeof null === "object";
В первой реализации JavaScript значения были представлены парой тип тега и значение. Тип тега для объектов равнялся 0. null был представлен как нулевой указатель (0x00 в большинстве платформ). Следовательно, тип тега для null равнялся нулю, поэтому возвращаемое значение typeof является фиктивным. (подробнее)
Исправление было предложено в ECMAScript (через отключение), но было отклонено. Это привело бы к тому, что typeof null === ‘null’ .
Использование оператора new
// Все функции-конструкторы, созданные с помощью 'new', будут иметь тип 'object' var str = new String("String"); var num = new Number(100); typeof str; // Вернёт 'object' typeof num; // Вернёт 'object' // Но существует исключение для конструктора Function var func = new Function(); typeof func; // Вернёт 'function'
Регулярные выражения
Вызываемые регулярные выражения были нестандартным дополнением в некоторых браузерах.
typeof /s/ === "function"; // Chrome 1-12 Не соответствует ECMAScript 5.1 typeof /s/ === "object"; // Firefox 5+ Соответствует ECMAScript 5.1
Ошибки, связанные с временными мёртвыми зонами
До ECMAScript 2015, гарантировалось, что оператор typeof вернёт строку для любого операнда, с которым он был вызван. Это изменилось после добавления не поднимающихся объявлений let and const с блочной областью видимости. Теперь, если переменные объявлены с помощью let и const , и для них вызывается typeof в блоке объявления переменных, но до объявления, то выбрасывается ReferenceError . Поведение отличается от необъявленных переменных, для которых typeof вернёт ‘undefined’. Переменные с блочной областью видимости находятся в «временной мёртвой зоне», которая длится от начала блока до момента объявления переменных. В этой зоне попытка доступа к переменным выбрасывает исключение.
typeof undeclaredVariable === "undefined"; typeof newLetVariable; let newLetVariable; // ReferenceError typeof newConstVariable; const newConstVariable = "hello"; // ReferenceError
Исключения
Во всех текущих браузерах существует нестандартный host-объект document.all , который имеет тип Undefined.
typeof document.all === "undefined";
Хотя спецификация разрешает собственные имена типов для нестандартных экзотических объектов, требуется чтобы эти имена отличались от предопределённых. Ситуация, когда document.all имеет тип undefined должна рассматриваться как исключительное нарушение правил.
Спецификации
| Specification |
|---|
| ECMAScript Language Specification # sec-typeof-operator |
Совместимость с браузерами
BCD tables only load in the browser
IE-специфичные замечания
В IE 6, 7 и 8 многие host-объекты являются объектами, но не функциями. Например:
typeof alert === "object";
Смотрите также
- instanceof
- Why typeof is no longer «safe»
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 7 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
MDN
Support
- Product help
- Report an issue
Our communities
Developers
- Web Technologies
- Learn Web Development
- MDN Plus
- Hacks Blog
- Website Privacy Notice
- Cookies
- Legal
- Community Participation Guidelines
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2024 by individual mozilla.org contributors. Content available under a Creative Commons license.
Оператор typeof
Оператор typeof позволяет определить тип параметра (число, строка, объект). Оператор возвращает строку, содержащую тип ( ‘number’ , ‘string’ , ‘object’ ).
Для null оператор возвращает ‘object’ (это признанная ошибка языка). Для функций оператор возвращает ‘function’ . Это сделано для удобства, так как типа ‘function’ не существует.
Синтаксис
У оператора typeof есть 2 синтаксиса (оба синтаксиса работают одинаково):
typeof параметр; typeof(параметр);
Пример
Давайте посмотрим, как typeof работает с числом:
В результате выполненного кода мы получим значение number :
Пример
Теперь давайте зададим в параметре строку:
typeof ‘str’;
Результат выполнения кода:
Пример
Теперь укажем в параметре булевое значение true :
typeof true;
Результат выполнения кода:
Пример
Давайте посмотрим какой тип у значения undefined :
typeof undefined;
После выполнения кода мы получим также undefined :
Пример
Теперь давайте узнаем тип пустого объекта:
Результат выполнения кода:
Пример
А теперь узнаем тип пустого массива:
В результате также получим ‘object’ :
Пример
Давайте узнаем тип значения null :
typeof null;
В результате также получим ‘object’ , что является признанной ошибкой языка:
Пример
Теперь определим тип пустой функции:
typeof function() <>;
После выполнения кода мы получим ‘function’ , несмотря на то, что такого типа не существует. Данная строка нужна для удобства пользователя при определении функции:
Пример
Напишем функцию, которая будет выводить только числа:
function printNumber(number) < if (typeof number === 'number') < console.log(number); >> printNumber(2); printNumber(‘str’); printNumber(3);
Смотрите также
- функцию isNaN ,
которая осуществляет проверку на NaN - функцию isFinite ,
которая проверяет число на конечность
«typeid» против «typeof» в C++
кроме того, вот тестовый тест кода, который я создал где я это обнаружил!—2—> не возвращает то, что я ожидал. Почему?
main.cpp
#include #include //for 'typeid' to work class Person < public: // . Person members . virtual ~Person() <>>; class Employee : public Person < // . Employee members . >; int main () < Person person; Employee employee; Person *ptr = &employee; int t = 3; std::cout
выход:
bash-3.2$ g++ -Wall main.cpp -o main bash-3.2$ ./main i 6Person 8Employee P6Person 8Employee
автор: abhi
6 ответов
язык C++ не имеет такой вещи, как typeof . Вы, должно быть, смотрите на какое-то расширение для компилятора. Если вы говорите о GCC typeof , то аналогичная функция присутствует в C++11 через ключевое слово decltype . Опять же, C++ не имеет такого typeof ключевое слово.
typeid - оператор языка C++, который возвращает идентификационную информацию типа во время выполнения. Он в основном возвращает type_info объект, который равен-сопоставим с другими type_info объекты.
обратите внимание, что единственное определенное свойство возвращаемого type_info объект имеет то, что его равенство-и неравенство-сопоставимо, т. е. type_info объекты, описывающие различные типы, сравниваются неравными, в то время как type_info объекты, описывающие один и тот же тип надо сравнивать равные. Все остальное определяется реализацией. Методы, которые возвращают различные "имена", не гарантируют возврата чего-либо читаемого человеком и даже не гарантируют возврата чего-либо в все.
обратите внимание также, что вышеизложенное, вероятно, подразумевает (хотя стандарт, похоже, не упоминает об этом явно), что последовательные приложения typeid к тому же типу могут возвращать разные type_info объекты (которые, конечно, все равно придется сравнивать равные).
основное различие между ними состоит в следующем
- typeof-это конструкция времени компиляции и возвращает тип, определенный во время компиляции
- typeid является конструкцией времени выполнения и, следовательно, дает информацию о типе времени выполнения значения.
автор: JaredPar
typeid может работать во время выполнения и возвращать объект, описывающий тип времени выполнения объекта, который должен быть указателем на объект класса с виртуальными методами для RTTI (информация о типе времени выполнения) для хранения в классе. Он также может дать тип времени компиляции выражения или имя типа, если не указан указатель на класс с информацией о типе времени выполнения.
typeof является расширением GNU и дает вам тип любого выражения во время компиляции. Это может быть полезно, например, при объявлении временных переменных в макросах, которые могут использоваться для нескольких типов. В C++, вы обычно используете шаблоны.
автор: Brian Campbell
отвечая на дополнительный вопрос:
мой следующий тестовый код для typeid делает не выводите правильное имя типа. что случилось?
нет ничего плохого. Вы видите строковое представление имени типа. Стандартный C++ не заставляет компиляторы выдавать точное имя класса, это просто до реализации(поставщика компилятора), чтобы решить, что подходит. Короче говоря, имена до компилятор.
это два разных инструмента. typeof возвращает тип выражения, но он не является стандартным. В C++0x есть что-то под названием decltype который выполняет ту же работу AFAIK.
decltype(0xdeedbeef) number = 0; // number is of type int! decltype(someArray[0]) element = someArray[0];
, тогда как typeid используется с полиморфными типами. Например, скажем, что cat выводит animal :
animal* a = new cat; // animal has to have at least one virtual function . if( typeid(*a) == typeid(cat) ) < // the object is of type cat! but the pointer is base pointer. >
автор: AraK
typeid предоставляет тип данных во время выполнения, когда его просят. Typedef-это конструкция времени компиляции, которая определяет новый тип, как указано после этого. В C++нет typeof Вывод отображается как (показано как записанные комментарии):
std::cout
автор: Dr. Debasish Jana
Вы можете использовать Boost demangle для выполнения красивого имени:
#include
To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);