programing

C # 7 : Out 변수의 밑줄 (_) 및 별표 (*)

nasanasas 2020. 11. 14. 10:16
반응형

C # 7 : Out 변수의 밑줄 (_) 및 별표 (*)


여기 에서 C # 7의 새로운 변수 기능에 대해 읽었 습니다 . 두 가지 질문이 있습니다.

  1. 그것은 말한다

    우리는 _당신이 신경 쓰지 않는 매개 변수를 무시할 수 있도록 a 형태의 out 매개 변수로 "discards" 를 허용합니다.

    p.GetCoordinates(out var x, out _); // I only care about x
    

    Q : C # 7.0 이전 버전에서도 그렇게 할 수 있기 때문에 이것은 정보 일 뿐이며 C # 7의 새로운 기능은 아닙니다.

    var _;
    if (Int.TryParse(str, out _))
    ...
    

    아니면 여기에 뭔가 빠졌나요?

  2. 동일한 블로그에서 언급 한대로 수행하면 내 코드에서 오류가 발생합니다.

    ~Person() => names.TryRemove(id, out *);
    

    *유효한 식별자가 아닙니다. Mads Torgersen의 감독 이요?


C # 7에서 Discards 는 변수가 선언 될 때마다-이름에서 알 수 있듯이-결과를 버리는 데 사용할 수 있습니다. 따라서 폐기는 out 변수와 함께 사용할 수 있습니다.

p.GetCoordinates(out var x, out _);

표현식 결과를 버리는 데 사용할 수 있습니다.

_ = 42;

예에서

p.GetCoordinates(out var x, out _);
_ = 42;

_도입되는 변수가 없습니다 . 폐기가 사용되는 경우는 두 가지뿐입니다.

그러나 _범위에 식별자 있으면 폐기를 사용할 수 없습니다.

var _ = 42;
_ = "hello"; // error - a string cannot explicitly convert from string to int

이에 대한 예외는 _변수가 출력 변수로 사용되는 경우입니다. 이 경우 컴파일러는 또는 유형을 무시하고 var폐기로 처리합니다.

if (p.GetCoordinates(out double x, out double _))
{
    _ = "hello"; // works fine.
    Console.WriteLine(_); // error: _ doesn't exist in this context.
}

이 경우 out var _또는 out double _이 사용되는 경우에만 발생합니다 . 사용 out _하면 기존 변수에 대한 참조로 처리됩니다 ( _예 : 범위에있는 경우).

string _;
int.TryParse("1", out _); // complains _ is of the wrong type

마지막으로,이 *표기법은 폐기에 대한 논의 초기에 제안 되었지만 _후자가 다른 언어에서 더 일반적으로 사용되는 표기법이기 때문에 포기되었습니다 .


_C # 7에서 Discard 연산자의 또 다른 예 는 최근 C # 7에서 추가 된 문 에서 유형의 변수 패턴 일치 시키는 것입니다 .objectswitch

암호:

static void Main(string[] args)
{
    object x = 6.4; 
    switch (x)
    {
        case string _:
            Console.WriteLine("it is string");
            break;
        case double _:
            Console.WriteLine("it is double");
            break;
        case int _:
            Console.WriteLine("it is int");
            break;
        default:
            Console.WriteLine("it is Unknown type");
            break;
    }

    // end of main method
}

이 코드는 유형과 일치하고 case ... _.


더 궁금해

다음 스 니펫을 고려하십시오.

static void Main(string[] args)
{
    //....
    int a;
    int b;

    Test(out a, out b);
    Test(out _, out _);    
    //....
}

private static void Test(out int a, out int b)
{
    //...
}

이것은 무슨 일이 일어나고 있는지 :

...

13:             int  a;
14:             int  b;
15: 
16:             Test(out a, out b);
02340473  lea         ecx,[ebp-40h]  
02340476  lea         edx,[ebp-44h]  
02340479  call        02340040  
0234047E  nop  
    17:             Test(out _, out _);
0234047F  lea         ecx,[ebp-48h]  
02340482  lea         edx,[ebp-4Ch]  
02340485  call        02340040  
0234048A  nop 

...

이면에서 볼 수 있듯이 두 통화는 같은 일을합니다.

@ Servé Laurijssen이 지적했듯이 멋진 점은 일부 값에 관심이없는 경우 편리한 변수 미리 선언 할 필요가 없다는 것입니다.


첫 번째 질문에 대해

C # 7.0 이전 버전에서도 그렇게 할 수 있기 때문에 이것은 정보 일 뿐이며 C # 7의 새로운 기능은 아닙니다.

var _;
if (Int.TryParse(str, out _))
    // ...

The novelty is that you dont have to declare _ anymore inside or outside the expression and you can just type

int.TryParse(s, out _);

Try to do this one liner pre C#7:

private void btnDialogOk_Click_1(object sender, RoutedEventArgs e)
{
     DialogResult = int.TryParse(Answer, out _);
}

In C# 7.0 (Visual Studio 2017 around March 2017), discards are supported in assignments in the following contexts:


Other useful notes

  • discards can reduce memory allocations. Because they make the intent of your code clear, they enhance its readability and maintainability
  • Note that _ is also a valid identifier. When used outside of a supported context

Simple example : here we do not want to use the 1st and 2nd params and only need the 3rd param

(_, _, area) = city.GetCityInformation(cityName);

Advanced example in switch case which used also modern switch case pattern matching (source)

switch (exception)                {
case ExceptionCustom exceptionCustom:       
        //do something unique
        //...
    break;
case OperationCanceledException _:
    //do something else here and we can also cast it 
    //...
    break;
default:
    logger?.Error(exception.Message, exception);
    //..
    break;

}

참고URL : https://stackoverflow.com/questions/42920622/c7-underscore-star-in-out-variable

반응형