Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the principle of C # nullable type?

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "what is the principle of C# nullable type". In daily operation, I believe that many people have doubts about what the principle of C# nullable type is. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the question of "what is the principle of C# nullable type?" Next, please follow the editor to study!

For the convenience of demonstration, I will define an int? Type to receive both non-null and null cases.

Static void Main (string [] args)

{

Int? Num1 = 10

Int? Num2 = null

Console.WriteLine ("execution is over!")

Console.ReadLine ()

}

1. Dig IL code

It is easy to dig the IL code, just use the ILSPY gadget. The compiled IL code is as follows:

.method private hidebysig static

Void Main (

String [] args

) cil managed

{

/ / Method begins at RVA 0x2048

/ / Code size 36 (0x24)

.maxstack 2

.entrypoint

.locals init (

[0] valuetype [mscorlib] system. Nullable`1 num1

[1] valuetype [mscorlib] system. Nullable`1 num2

)

IL_0000: nop

IL_0001: ldloca.s 0

IL_0003: ldc.i4.s 10

IL_0005: call instance void valuetype [mscorlib] system. Nullable`1:: .ctor (! 0)

IL_000a: ldloca.s 1

IL_000c: initobj valuetype [mscorlib] system. Nullable`1

IL_0012: ldstr "execution is over!"

IL_0017: call void [mscorlib] System.Console::WriteLine (string)

IL_001c: nop

IL_001d: call string [mscorlib] System.Console::ReadLine ()

IL_0022: pop

IL_0023: ret

} / / end of method Program::Main

This IL code is still very easy to understand, much simpler than assembly (┬ _ ┬), you can see int? It's System.Nullable, and you can see from the valuetype tag that it's a value type, so turning the above code into C # code is like this.

{

Static void Main (string [] args)

{

/ / int? Num1 = 10

/ / int? Num2 = null

Nullable num3 = new Nullable (10)

Nullable num4 = new Nullable ()

Console.WriteLine ("execution is over!")

Console.ReadLine ()

}

It's very simple, so how to output num3 and num4? It would be nice to just Console.WriteLine.

You must have a question here: why does num3 output 10 and num4 outputs nothing? Haha, this is because Nullable's ToString () has been rewritten. Let's take a look at how ToString is rewritten. The code is as follows:

Public struct Nullable where T: struct

{

Private bool hasValue

Internal T value

[NonVersionable]

[_ _ DynamicallyInvokable]

Public Nullable (T value)

{

This.value = value

HasValue = true

}

[_ _ DynamicallyInvokable]

Public override string ToString ()

{

If (! hasValue)

{

Return ""

}

Return value.ToString ()

}

}

You can see that the ToString method either returns an empty string or the value you stuffed in the constructor. This is as simple as this, just dig up the IL code here.

two。 Dig machine code

To see the machine code of num1 and num2, you can actually look at the memory layout of Nullable. Here I use windbg, or use! clrstack-l to view the thread stack.

Int? Num1 = 10

Int? Num2 = null

0RV 007 > ~ 0s

Ntdllqualified ZwReadFilekeeper 0x14:

00007ffc`ec11aa64 c3 ret

0VOU 000 >! clrstack-l

OS Thread Id: 0x5364 (0)

Child SP IP Call Site

ConsoleApp4.Program.Main (System.String []) [C:\ dream\ Csharp\ ConsoleApp1\ ConsoleApp4\ Program.cs @ 21]

LOCALS:

0x00000018a9dfeaf8 = 0x0000000a00000001

0x00000018a9dfeaf0 = 0x0000000000000000

00000018a9dfed08 00007ffcd5b66c93 [GCFrame: 00000018a9dfed08]

As you can see from LOCALS, the contents stored on the thread stack of num1 and num2 are 0x0000000a00000001 and 0x0000000000000000, respectively, but this value is also very strange, one is 1 and the other is 0. We use the dd command to dump the address.

0RV 000 > dd 0x00000018a9dfeaf8

00000018`a9dfeaf8 00000001 00000a a9dfec08 00000018

0RV 000 > dd 0x00000018a9dfeaf0

00000018`a9dfeaf0 00000000 00000000 00000001 00000a

There is a hexadecimal value of 0000000a in the memory area of num1, which is decimal 10, so what is the first 00000001? Don't forget, int? It's grammar candy. You're looking at Nullable now.

You can see clearly that there are two value type fields in this structure, and naturally 00000001 is hasValue=true. Num2 is also easy to understand, the two default values are two zeros. 00000000 00000000 .

Three: there is an unexpected discovery

1. Int? Takes up more memory than int

If you have a large amount of data in memory, you should be careful, int? It takes 4 bytes more than int on x64, that is, twice as much, regardless of thread stack or managed heap.

two。 Why does bool occupy 4 bytes of space?

Demo on thread stack

Some people must be wondering, isn't bool just a byte in C #? How do you say 4 bytes? If you ask me, I can only say that from the point of view of windbg, the thread stack of x64 system is based on 4 bytes. If you don't believe me, I will define the value types of different fields in the code. Just look at the distribution on the thread stack and speak with the facts.

Byte b1 = byte.MaxValue

Byte b2 = byte.MaxValue

Short b3 = short.MaxValue

Short b4 = short.MaxValue

Int b5 = int.MaxValue

Int b6 = int.MaxValue

0VOU 000 >! clrstack-l

OS Thread Id: 0xa98 (0)

ConsoleApp4.Program.Main (System.String []) [C:\ dream\ Csharp\ ConsoleApp1\ ConsoleApp4\ Program.cs @ 25]

LOCALS:

0x000000a8395fedbc = 0x00000000000000ff

0x000000a8395fedb8 = 0x00000000000000ff

0x000000a8395fedb4 = 0x0000000000007fff

0x000000a8395fedb0 = 0x0000000000007fff

0x000000a8395fedac = 0x000000007fffffff

0x000000a8395feda8 = 0x000000007fffffff

Then dump the smallest address, 0x000000a8395feda8.

0RV 000 > dd 0x000000a8395feda8

000000a8`395feda8 7fffffff 7fffffff 00007fff 00007fff

000000a8`395fedb8 000000ff 000000ff 395feec8 000000a8

000000a8`395fedc8 395fefc8 000000a8 395fee00 000000a8

000000a8`395fedd8 d5b66c93 00007ffc 98e72d30 000001ee

000000a8`395 fede8 76504140 00007ffc 00000000 00000000

000000a8`395fedf8 00000000 00007ffc 395feef0 000000a8

000000a8`395 08 971d0b20 000001ee 00000000 00000000

000000a8`395 18 d5b66b79 00007ffc 00000000 00000000

By comparison, you can see that the above 7fffffff, 00007fff MaxValue 000000ff is the corresponding int,short,byte MaxValue, which takes up 4 bytes of space, all right?

Managed heap demonstration

Var arr1 = new int [] {10}

Var arr2 = new int? [] {14}

0VOU 000 >! clrstack-l

OS Thread Id: 0x23f8 (0)

000000859a1fec60 00007ffc76630967 ConsoleApp4.Program.Main (System.String []) [C:\ dream\ Csharp\ ConsoleApp1\ ConsoleApp4\ Program.cs @ 32]

LOCALS:

0x000000859a1feca0 = 0x000002773cb32d70

0x000000859a1fec98 = 0x000002773cb32d90

000000859a1feeb8 00007ffcd5b66c93 [GCFrame: 000000859a1feeb8]

0VOU 000 >! do 0x000002773cb32d70

Name: System.Int32 []

MethodTable: 00007ffcd2d58538

EEClass: 00007ffcd2ec5918

Size: 28 (0x1c) bytes

Array: Rank 1, Number of elements 1, Type Int32 (Print Array)

Fields:

None

0VOU 000 >! do 0x000002773cb32d90

Name: system. Nullable`1 [[System.Int32, mscorlib]] []

MethodTable: 00007ffcd3fb2058

EEClass: 00007ffcd30221a0

Size: 32 (0x20) bytes

Array: Rank 1, Number of elements 1, Type VALUETYPE (Print Array)

Fields:

None

0VOU 000 >! objsize 0x000002773cb32d70

Sizeof (000002773cb32d70) = 32 (0x20) bytes (System.Int32 [])

0VOU 000 >! objsize 0x000002773cb32d90

Sizeof (000002773cb32d90) = 32 (0x20) bytes (system. Nullable`1 [[System.Int32, mscorlib]] [])

As you can see, one is 28byte, the other is 32byte, and the extra one is that hasValue, ha. One thing to note is that 32byte is typed out with! objsize, this is because 28byte is changed into 32byte by 8 alignment, and then I dump the two value types, as shown in the following figure:

At this point, the study on "what is the principle of C# nullable type" is over. I hope to be able to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report