Система. Int32 содержит … другая Система. Int32

TypeScript 3.4 rc получил опцию компилятора --incremental ( сообщение в блоге ).

Когда он включен, TypeScript сгенерирует файл .tsbuildinfo, если его еще нет (поэтому вы все равно играете штраф 10 с + один раз). Но если он существует, холодный tsc --watch пробег будет очень быстрым (больше не задержка 10 с).

Как включить инкрементные сборки

Либо с флагом командной строки --incremental, либо в вашем tsconfig.json:

{
    "compilerOptions": {
        "incremental": true
    }
}

14
задан zneak 22 February 2018 в 05:19
поделиться

4 ответа

Как уже отмечалось, 32-битное целое число может существовать в двух вариантах. Четыре байта в любом месте памяти или регистра ЦП (не только в стеке), быстрая версия. И его можно встроить в System.Object, коробочную версию. Объявление System.Int32 совместимо с последним. В упаковке он имеет типичный заголовок объекта, за которым следуют 4 байта, в которых хранится значение. И эти 4 байта точно соответствуют члену m_value. Возможно, вы понимаете, почему здесь нет конфликта: m_value всегда быстрая версия без упаковки. Потому что не существует такой вещи, как целое число в штучной упаковке.

Как компилятор языка, так и JIT-компилятор хорошо осведомлены о свойствах Int32.Компилятор отвечает за решение, когда целое число нужно упаковать и распаковать, для этого он генерирует соответствующие инструкции IL. И он знает, какие доступны инструкции IL, которые позволяют работать с целым числом, не упаковывая его предварительно. Как легко понять из методов, реализованных System.Int32, например, он не имеет переопределения для operator == (). Это делается с помощью кода операции CEQ. Но у него есть переопределение для Equals (), необходимое для переопределения метода Object.Equals (), когда целое число помещено в рамку. Ваш компилятор должен иметь такую ​​же осведомленность.

3
ответ дан 1 December 2019 в 16:44
поделиться

Объяснение

Другие ответы являются неосведомленными и/или вводящими в заблуждение.

 

Пролог

Это может помочь понять это под первым чтением мой ответ на [1 144], Как ValueTypes происходят из Объекта (ReferenceType) и все еще ValueTypes?

 

Поэтому, что продолжается?

System.Int32 структура, которая содержит 32-разрядное целое число со знаком. Это делает не , содержат себя. Для ссылки на тип значения в IL синтаксис valuetype [assembly]Namespace.TypeName.

Встроенные типы II.7.2 CLI встроенным типам определили соответствующие типы значения в Библиотеке базовых классов. На них нужно сослаться в подписях только с помощью их специальной кодировки (т.е. не используя синтаксис valuetype TypeReference общего назначения). Раздел I указывает встроенные типы.

Это означает, что, если у Вас есть метод, который берет 32-разрядное целое число, Вы не должны использовать стандартное valuetype [mscorlib]System.Int32 синтаксис, но специальное кодирование для 32-разрядного встроенного целого числа со знаком int32.

В C#, это означает, это, будет ли Вы тип System.Int32 или int, любой скомпилирован в [1 112], не valuetype [mscorlib]System.Int32.

Вы, возможно, услышали, что int псевдоним для [1 115] в C#, но в действительности, оба псевдонимы встроенного типа int32.

значения CLS Поэтому, в то время как структура как [1 162]

public struct MyStruct
{
    internal MyStruct m_value;
}

Действительно скомпилировала бы в (и таким образом была бы недопустима):

.class public sequential ansi sealed beforefieldinit MyStruct extends [mscorlib]System.ValueType
{
    .field assembly valuetype MyStruct m_value;
}

 

namespace System
{
    public struct Int32
    {
        internal int m_value;
    }
}

Вместо этого компиляции к (игнорирующие интерфейсы):

.class public sequential ansi sealed beforefieldinit System.Int32 extends [mscorlib]System.ValueType
{
    .field assembly int32 m_value;
}

компилятор C# делает не , нуждаются в особом случае для компиляции System.Int32, потому что спецификация CLI предусматривает, что все ссылки на [1 118] заменяются специальным кодированием для встроенного типа int32.Следовательно. System.Int32 значения CLS, структура, которая не содержит другой System.Int32, но int32. В IL у Вас может быть 2 перегрузки метода, одно взятие System.Int32 и другое взятие int32 и сделать, чтобы они сосуществовали:

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
  .ver 2:0:0:0
}
.assembly test {}
.module test.dll
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003
.corflags 0x00000001
.class MyNamespace.Program
{
    .method static void Main() cil managed
    {
        .entrypoint
        ldc.i4.5
        call int32 MyNamespace.Program::Lol(valuetype [mscorlib]System.Int32) // Call the one taking the System.Int32 type.
        call int32 MyNamespace.Program::Lol(int32) // Call the overload taking the built in int32 type.
        call void [mscorlib]System.Console::Write(int32)
        call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
        pop
        ret
    }

    .method static int32 Lol(valuetype [mscorlib]System.Int32 x) cil managed
    {
        ldarg.0
        ldc.i4.1
        add
        ret
    }

    .method static int32 Lol(int32 x) cil managed
    {
        ldarg.0
        ldc.i4.1
        add
        ret
    }
}

Декомпиляторы как ILSpy, dnSpy, Отражатель.NET, и т.д. могут вводить в заблуждение. Они (во время записи) будут декомпилироваться и int32 и System.Int32 или как ключевое слово int C# или как тип System.Int32, потому что это - то, как мы определяем целые числа в C#.

, Но int32 встроенный тип значения для 32-разрядных целых чисел со знаком (т.е. VES имеет прямую поддержку этих типов, с инструкциями как [1 130], sub, ldc.i4.x, и т.д.); System.Int32 соответствующий тип значения, определенный в библиотеке классов. Соответствие System.Int32 тип используется для упаковки, и для методов как [1 135], CompareTo(), и т.д.

 

, Если Вы пишете программу в чистом IL, можно абсолютно заставить собственное значение ввести, который содержит int32 точно таким же образом, где Вы все еще используете int32, но методы вызова на пользовательском "соответствующем" типе значения.

.class MyNamespace.Program
{
    .method hidebysig static void  Main(string[] args) cil managed
    {
        .entrypoint
        .maxstack 8
        ldc.i4.0
        call void MyNamespace.Program::PrintWhetherGreaterThanZero(int32)
        ldc.i4.m1 // -1
        call void MyNamespace.Program::PrintWhetherGreaterThanZero(int32)
        ldc.i4.3
        call void MyNamespace.Program::PrintWhetherGreaterThanZero(int32)
        ret
    }

    .method private hidebysig static void PrintWhetherGreaterThanZero(int32 'value') cil managed noinlining 
    {
        .maxstack 8
        ldarga 0
        call instance bool MyCoolInt32::IsGreaterThanZero()
        brfalse.s printOtherMessage

        ldstr "Value is greater than zero"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    printOtherMessage:
        ldstr "Value is not greater than zero"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}

.class public MyCoolInt32 extends [mscorlib]System.ValueType
{
    .field assembly int32 myCoolIntsValue;

    .method public hidebysig bool IsGreaterThanZero()
    {
        .maxstack 8

        ldarg.0
        ldind.i4
        ldc.i4.0
        bgt.s isNonZero
        ldc.i4.0
        ret
    isNonZero:
        ldc.i4.1
        ret
    }
}

Это не отличается от эти System.Int32 тип, за исключением того, что компилятор C# не рассматривает MyCoolInt32 соответствие int32 тип, но к CLR, это не имеет значения. Это приведет к сбою PEVerify.exe, однако, но это будет работать очень хорошо. Декомпиляторы покажут броски, и очевидный указатель разыменовывает при декомпиляции вышеупомянутого, потому что они не рассматривают MyCoolInt32 и int32 связанный также.

, Но функционально, нет никакого различия, и нет никакого волшебства, продолжающегося негласно в CLR.

0
ответ дан 1 December 2019 в 16:44
поделиться

Зайдите в эту ветку для кропотливого обсуждения этой тайны.

1
ответ дан 1 December 2019 в 16:44
поделиться

Магия на самом деле в боксировании/небоксировании.

System.Int32 (и его псевдоним int) - это тип значения, что означает, что он обычно выделяется в стеке. CLR берет ваше объявление System.Int32 и просто превращает его в 32 бита стека.

Однако, когда вы пишете object testInt = 4;, компилятор автоматически превращает ваше значение 4 в ссылку, поскольку object является ссылочным типом. Что у вас есть, так это ссылка, указывающая на System.Int32, которая теперь занимает 32 бита места где-то на куче. Но автобоксированная ссылка на System.Int32 называется (...подождите...) System.Int32.

Что делает ваш пример кода, так это создает ссылку System.Int32 и изменяет значение System.Int32, на которое оно указывает. Это объясняет странное поведение.

0
ответ дан 1 December 2019 в 16:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: