program tip

null은 무엇입니까!

radiobox 2021. 1. 8. 08:03
반응형

null은 무엇입니까! 성명은 의미합니까?


최근에 다음 코드를 보았습니다.

public class Person
{
    //line 1
    public string FirstName { get; }
    //line 2
    public string LastName { get; } = null!;
    //assign null is possible
    public string? MiddleName {get; } = null;

    public Person(string firstName, string lastName, string middleName)
    {
        FirstName = firstName;
        LastName = lastName;
        MiddleName = middleName;
    }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
        MiddleName = null;
    }
}

기본적으로 새로운 C # 8 기능을 파헤 치려고합니다. 그중 하나는입니다 NullableReferenceTypes. 사실 이미 그것에 대한 많은 기사와 정보가 있습니다. 예를 들어이 기사 는 꽤 좋습니다. 하지만이 새로운 진술에 대한 정보를 찾을 수 없습니다. null!누군가 나에게 설명을 해줄 수 있습니까? 왜 이것을 사용해야합니까? 그리고 사이의 차이가 무엇인가 line1와는 line2?


null!의미 를 이해하는 열쇠 !운영자를 이해하는 것 입니다. 이전에 "not"연산자로 사용했을 수 있습니다. 그러나 C # 8.0 이후 연산자는 Nullabilty를 제어하는 ​​형식에서도 사용할 수 있습니다.

!유형에 사용할 때 연산자 는 무엇입니까 ?

!연산자는 타입에서 사용될 때 호출 널 용서 조작 [ 문서 ]. C # 8.0에서 도입되었습니다.


기술적 설명

일반적인 사용법

이 정의를 가정하면 :

class Person
{
  public string? MiddleName;
}

사용법은 다음과 같습니다.

void LogPerson(Person person)
{
    Console.WriteLine(person.MiddleName.Length);  // WARNING: may be null
    Console.WriteLine(person.MiddleName!.Length); // No warning
}

이 연산자는 기본적으로 컴파일러 널 검사를 해제합니다.

내부 작업

이 연산자를 사용하면 컴파일러에 null 일 수있는 항목에 액세스해도 안전함을 알 수 있습니다. 이 경우 널 안전성에 대해 "관심 없음"을 표시합니다.

널 안전성에 대해 이야기 할 때 변수가있을 수있는 두 가지 상태가 있습니다.

  • Nullable- null 일 있습니다.
  • Non-Nullable-null 일 수 없습니다 .

C # 8.0부터 모든 참조 유형은 기본적으로 nullable이 아닙니다.

"nullability"는 다음 두 가지 새로운 유형 연산자로 수정할 수 있습니다.

  • !=에서 NullableNon-Nullable
  • ?=에서 Non-NullableNullable

이 연산자는 기본적으로 서로 대응합니다. 컴파일러는 해당 연산자로 정의한 정보를 사용하여 널 안전성을 보장합니다.

? 운영자 사용.

  1. 널 가능 string? x;

    • x 참조 유형이므로 기본적으로 nullable이 아닙니다.
    • ?연산자를 적용하여 null을 허용합니다.
    • x = null 잘 작동합니다.
  2. Null 불가 string y;

    • y 참조 유형이므로 기본적으로 nullable이 아닙니다.
    • y = null null이 아니어야하는 항목에 null 값을 할당 했으므로 경고를 생성합니다.

! 운영자 사용.

string x;
string? y = null;
  1. x = y

    • 불법! -Warning: "y" may be null
    • 할당의 왼쪽은 Null을 허용하지 않지만 오른쪽은 Null을 허용합니다.
  2. x = y!

    • 적법한!
    • 할당의 오른쪽과 왼쪽은 null이 아닙니다.
    • 이후 작품 y!적용 !연산자에 y있는이 비 null 허용합니다.

WARNING The ! operator only turns off the compiler-checks at a type-system level - At runtime, the value may still be null.

This is an Anti-Pattern.

You should try to avoid using the ! Null-Forgiving-Operator.

There are valid use-cases ( outlined in detail below ) like unit-tests where this operator is appropriate to use. In 99% of the cases though, you are better off with an alternative solution. Please do not slap dozens of !'s in your code, just to silence the warnings. Think if your cause really warrants the use.

Use - but with care. If there is no concrete purpose / use-case prefer not to use it.

It negates the effects of null-safety you get guaranteed by the compiler.

Using the ! operator will create very hard to find bugs. If you have a property that is marked non-nullable, you will assume you can use it safely. But at runtime, you suddenly run into a NullReferenceException and scratch your head. Since a value actually became null after bypassing the compiler-checks with !.

Why does this operator exist then?

  • In some edge cases, the compiler is not able to detect that a nullable value is actually non-nullable.
  • Easier legacy code-base migration.
  • In some cases, you just don't care if something becomes null.
  • When working with Unit-tests you may want to check the behavior of code when a null comes through.

Answering your question specifically.

So what does null! mean?

It tells the compiler that null is not a null value. Sounds weird, doesn't it?

It is the same as y! from the example above. It only looks weird since you apply the operator to the null literal. But the concept is the same.

Picking apart what is happening.

public string LastName { get; } = null!;

This line defines a non-nullable class property named LastNameof type string. Since it is non-nullable you can technically not assign null to it - obviously.

But you do just that - assign null to LastName - by using the ! operator. Because null! is not null - as far as the compiler is concerned about null-safety.


When the "nullable reference types" feature is turned on, the compiler tracks which values in your code it thinks may be null or not. There are times where the compiler could have insufficient knowledge.

For example, you may be using a delayed initialization pattern, where the constructor doesn't initialize all the fields with actual (non-null) values, but you always call an initialization method which guarantees the fields are non-null. In such case, you face a trade-off:

  • if you mark the field as nullable, the compiler is happy, but you have to un-necessarily check for null when you use the field,
  • if you leave the field as non-nullable, the compiler will complain that it is not initialized by the constructors (you can suppress that with null!), then the field can be used without null check.

Note that by using the ! suppression operator, you are taking on some risk. Imagine that you are not actually initializing all the fields as consistently as you thought. Then the use of null! to initialize a field covers up the fact that a null is slipping in. Some unsuspecting code can receive a null and therefore fail.

More generally, you may have some domain knowledge: "if I checked a certain method, then I know that some value isn't null":

if (CheckEverythingIsReady())
{
   // you know that `field` is non-null, but the compiler doesn't. The suppression can help
   UseNonNullValueFromField(this.field!);
}

Again, you must be confident of your code's invariant to do this ("I know better").

ReferenceURL : https://stackoverflow.com/questions/54724304/what-does-null-statement-mean

반응형