C\#중 9 개의'흑 마법'

12373 단어 c#흑 마술
우 리 는C#매우 선진 적 인 언어 라 는 것 을 안다.왜냐하면 그것 은 멀리 볼 수 있 는'문법 사탕'이기 때문이다.이런'문법 사탕'들 은 때때로 너무 쓰기 좋아 서 어떤 사람들 은 그것 이C#컴 파일 러 가 죽은 것 이 라 고 생각 하고 이치 에 맞지 않 는 다―약간'흑 마법'과 같다.
그러면 우 리 는C#이런 고급 언어 기능 이 컴 파일 러 가 죽은 것('흑 마법')인지,아니면 확장 할 수 있 는'오리 유형'인지 볼 수 있다.
제 가 먼저 디 렉 터 리 를 만 들 겠 습 니 다.여러분 은 이 디 렉 터 리 에 대해'흑 마법'(컴 파일 러 가 죽 었 다 고 쓰 여 있 는 지)인지'오리 유형'인지 판단 해 보 세 요.
  • LINQ 작업,IEnumerable형식;
  • async/await,Task/ValueTask 유형;
  • 표현 식 트 리 와 Expression형식;
  • 플러그 인 문자열 과 Formattable String 형식;
  • yield return,IEnumerable형식 과;
  • foreach 순환,IEnumerable형식;
  • using 키워드,IDisposable 인터페이스;
  • T?,Nullable형식 과;
  • 임의의 종류의 Index/Range 범 형 작업.
  • 1.LINQ조작,그리고IEnumerable<T>유형
    '흑 마술'이 아니 라'오리 스타일'입 니 다.LINQC# 3.0발표 한 새로운 기능 으로 데 이 터 를 매우 편리 하 게 조작 할 수 있다.현재12년 이 지 났 습 니 다.비록 일부 기능 이 강화 되 어야 하지만 다른 언어 에 비해 훨씬 편리 합 니 다.
    제 가 지난 블 로그 에서 언급 한 바 와 같이LINQIEnumerable<T>을 바탕 으로 하 는 것 이 아니 라 하나의 유형 을 정 하고 필요 한LINQ표현 식 을 실현 하면 됩 니 다.LINQselect키 워드 는 호출.Select방법 으로 다음 과 같은'소조 작'으로'꽃 을 옮 겨 나 무 를 연결 하 는'효 과 를 실현 할 수 있 습 니 다.
    
    void Main()
    {
     var query = 
      from i in new F()
      select 3;
      
     Console.WriteLine(string.Join(",", query)); // 0,1,2,3,4
    }
    
    class F
    {
     public IEnumerable<int> Select<R>(Func<int, R> t)
     {
      for (var i = 0; i < 5; ++i)
      {
       yield return i;
      }
     }
    }
    2.async/awaitTask/ValueTask유형
    '흑 마술'이 아니 라'오리 스타일'입 니 다.async/awaitC# 5.0에 발표 되 었 고 비동기 프로 그래 밍 을 매우 편리 하 게 할 수 있 으 며 그 본질은 상태 기 이다.async/await의 본질은 다음 유형의 이름GetAwaiter()인 터 페 이 스 를 찾 는 것 이다.이 인 터 페 이 스 는INotifyCompletion또는ICriticalNotifyCompletion에 계승 되 는 종 류 를 되 돌려 야 하 며,이 종 류 는GetResult()방법 과IsComplete속성 을 실현 해 야 한다.
  • t.GetAwaiter()방법 을 먼저 호출 하여 대기 기 a 를 가 져 옵 니 다.
  • a.IsComplete 를 호출 하여 불 형식 b 를 가 져 옵 니 다.
  • b=true 라면 a.GetResult()를 즉시 실행 하여 실행 결 과 를 얻 습 니 다.
  • b=false 라면 상황 에 따라:
  • 만약 a 가 ICriticalNotifyComplete 를 실현 하지 못 했다 면,실행(a as INotifyComplete).OnComplete(action)
    만약 a 가 ICriticalNotifyComplete 를 실현 했다 면,실행(a as ICriticalNotifyComplete).OnComplete(action)
    실행 후 일시 정지,OnComplete 완료 후 다시 상태 기 로 돌아 가기;
    관심 있 는 방문 가능Github구체 적 인 규범 설명:https://github.com/dotnet/csharplang/blob/master/spec/expressions.md
    정상Task.Delay() 을 바탕 으로 다음 과 같은'소 조작'으로 하나의 단일 스 레 드TaskEx.Delay()를 실현 할 수 있다.
    
    static Action Tick = null;
    
    void Main()
    {
     Start();
     while (true)
     {
      if (Tick != null) Tick();
      Thread.Sleep(1);
     }
    }
    
    async void Start()
    {
     Console.WriteLine("    ");
     for (int i = 1; i <= 4; ++i)
     {
      Console.WriteLine($" {i} ,  :{DateTime.Now.ToString("HH:mm:ss")} -    :{Thread.CurrentThread.ManagedThreadId}");
      await TaskEx.Delay(1000);
     }
     Console.WriteLine("    ");
    }
    
    class TaskEx
    {
     public static MyDelay Delay(int ms) => new MyDelay(ms);
    }
    
    class MyDelay : INotifyCompletion
    {
     private readonly double _start;
     private readonly int _ms;
     
     public MyDelay(int ms)
     {
      _start = Util.ElapsedTime.TotalMilliseconds;
      _ms = ms;
     }
     
     internal MyDelay GetAwaiter() => this;
     
     public void OnCompleted(Action continuation)
     {
      Tick += Check;
      
      void Check()
      {
       if (Util.ElapsedTime.TotalMilliseconds - _start > _ms)
       {
        continuation();
        Tick -= Check;
       }
      }
     }
    
     public void GetResult() {}
     
     public bool IsCompleted => false;
    }
    실행 효 과 는 다음 과 같 습 니 다:
    실행 시작
    제 1 회,시간:17:38:03-스 레 드 번호:1
    두 번 째,시간:17:38:04-스 레 드 번호:1
    세 번 째,시간:17:38:05-스 레 드 번호:1
    제 4 회,시간:17:38:06-스 레 드 번호:1
    실행 완료
    굳이 사용 하지 않 아 도TaskCompletionSource<T>정 의 된async/await을 만 들 수 있 습 니 다.
    3.표현 식 트 리 와Expression<T>유형
    '흑 마법'입 니 다.'조작 공간'이 없습니다.형식 이Expression<T>일 때 만 표현 식 트 리 로 만 들 수 있 습 니 다. C# 3.0함께 발표 되면 서 멀리 내다 보 는'흑 마술'이다.
    다음 코드 와 같이:
    
    Expression<Func<int>> g3 = () => 3;
    컴 파 일 러 에 의 해 다음 과 같이 번 역 됩 니 다.
    
    Expression<Func<int>> g3 = Expression.Lambda<Func<int>>(
     Expression.Constant(3, typeof(int)), 
     Array.Empty<ParameterExpression>());
    4.플러그 인 문자열 과LINQ형식
    '흑 마술'입 니 다.'조작 공간'이 없습니다.FormattableString 에 발표 되 었 고 그 전에 많은 언어 들 이 비슷 한 기능 을 제공 했다.
    유형 이C# 6.0일 때 만 다음 코드 와 같은 다른 컴 파일 결 과 를 얻 을 수 있 습 니 다.
    
    FormattableString x1 = $"Hello {42}";
    string x2 = $"Hello {42}";
    컴 파일 러 생 성 결 과 는 다음 과 같 습 니 다.
    
    FormattableString x1 = FormattableStringFactory.Create("Hello {0}", 42);
    string x2 = string.Format("Hello {0}", 42);
    본질 적 으로FormattableString를 호출 하여 유형 을 만 드 는 것 이 므 로 주의 하 십시오.
    5.FormattableStringFactory.Createyield return유형;
    흑 마술 이지 만 보충 설명 이 있다.IEnumerable<T>yield return이외에IEnumerable<T>,IEnumerable,IEnumerator<T>,IEnumerator에 도 사용 할 수 있다.
    따라서C#C++/Javagenerator<T>행동 을 모 의 하려 면 간단 하 다.
    
    var seq = GetNumbers();
    seq.MoveNext();
    Console.WriteLine(seq.Current); // 0
    seq.MoveNext();
    Console.WriteLine(seq.Current); // 1
    seq.MoveNext();
    Console.WriteLine(seq.Current); // 2
    seq.MoveNext();
    Console.WriteLine(seq.Current); // 3
    seq.MoveNext();
    Console.WriteLine(seq.Current); // 4
    
    IEnumerator<int> GetNumbers()
    {
     for (var i = 0; i < 5; ++i)
      yield return i;
    }
    yield return―교체 기 는C# 2.0에 발표 되 었 다.
    6.foreach순환,IEnumerable<T>유형
    '오리 유형'으로'조작 공간'이 있 습 니 다.foreach굳이 사용IEnumerable<T>유형 에 협조 하지 않 고 대상 이 존재 하 는GetEnumerator()방법 만 있 으 면 된다.
    
    void Main()
    {
     foreach (var i in new F())
     {
      Console.Write(i + ", "); // 1, 2, 3, 4, 5, 
     }
    }
    
    class F
    {
     public IEnumerator<int> GetEnumerator()
     {
      for (var i = 0; i < 5; ++i)
      {
       yield return i;
      }
     }
    }
    또한 대상 이GetAsyncEnumerator()이 루어 지면await foreach비동기 순환 도 똑 같이 사용 할 수 있다.
    
    async Task Main()
    {
     await foreach (var i in new F())
     {
      Console.Write(i + ", "); // 1, 2, 3, 4, 5, 
     }
    }
    
    class F
    {
     public async IAsyncEnumerator<int> GetAsyncEnumerator()
     {
      for (var i = 0; i < 5; ++i)
      {
       await Task.Delay(1);
       yield return i;
      }
     }
    }
    await foreachC# 8.0과 함께 발 표 된 것 으로 내 가 전에 쓴'코드 프 리 젠 테 이 션 C\#버 전 별 새로운 기능'을 구체 적 으로 볼 수 있다.
    7. 키워드 와using인터페이스
    네,아니에요.IDisposable과 정상 적 인 키 워드 는using인 터 페 이 스 를 기반 으로 해 야 합 니 다.
    그러나IDisposableref struct는 또 다른 이야기 다.
    그러나 자원 을 방출 하 는 수요 가 여전히 존재 한다.어 떡 하지?'오리 유형'이 오 면 손 으로IAsyncDisposable방법 을 쓸 수 있 고 그 어떠한 인터페이스 도 계승 할 필요 가 없다.
    
    void S1Demo()
    {
     using S1 s1 = new S1();
    }
    
    ref struct S1
    {
     public void Dispose()
     {
      Console.WriteLine("    ");
     }
    }
    같은 이치 로ref struct인 터 페 이 스 를 사용 하면:
    
    async Task S2Demo()
    {
     await using S2 s2 = new S2();
    }
    
    struct S2 : IAsyncDisposable
    {
     public async ValueTask DisposeAsync()
     {
      await Task.Delay(1);
      Console.WriteLine("Async  ");
     }
    }
    8.ref struct 유형
    '흑 마법'으로 만 받 아들 일 수 있다 . 는 하나의Dispose()로 서 직접 받 아들 일 수 있다IAsyncDisposable값(정상T?은 받 아들 일 수 없다Nullable<T>값 이다.
    예제 코드 는 다음 과 같다.
    
    int? t1 = null;
    Nullable<int> t2 = null;
    int t3 = null; // Error CS0037: Cannot convert null to 'int' because it is a non-nullable value type
    생 성 코드 는 다음 과 같 습 니 다Nullable<T>.T?와 똑 같 습 니 다.컴 파일 에 실패 한 코드 를 건 너 뛰 었 습 니 다):
    
    IL_0000: nop
    IL_0001: ldloca.s 0
    IL_0003: initobj valuetype [System.Runtime]System.Nullable`1<int32>
    IL_0009: ldloca.s 1
    IL_000b: initobj valuetype [System.Runtime]System.Nullable`1<int32>
    IL_0011: ret
    9.임의의 유형의Nullable<T>범 형 조작
    '흑 마법'도 있 고'오리 유형'도 있다.조작 공간 이 존재 한다. null에 발표 되 어 처럼 색인 위 치 를 편리 하 게 조작 하고 대응 치 를 꺼 낼 수 있다.예전 에는 호출null등 복잡 한 조작 이 필 요 했 는데 지금 은 매우 간단 하 다.
    
    string url = "https://www.super-cool.com/product/7705a33a-4d2c-455d-a42c-c95e6ac8ee99/summary";
    string productId = url[35..url.LastIndexOf("/")];
    Console.WriteLine(productId);
    생 성 코드 는 다음 과 같 습 니 다:
    
    string url = "https://www.super-cool.com/product/7705a33a-4d2c-455d-a42c-c95e6ac8ee99/amd-r7-3800x";
    int num = 35;
    int length = url.LastIndexOf("/") - num;
    string productId = url.Substring(num, length);
    Console.WriteLine(productId); // 7705a33a-4d2c-455d-a42c-c95e6ac8ee99
    이 를 통 해 알 수 있 듯 이int?컴 파일 러 는 무시Nullable<int>하고 호출Index/Range으로 직접 번역 했다.
    그러나 배열 은 다르다.
    
    var range = new[] { 1, 2, 3, 4, 5 }[1..3];
    Console.WriteLine(string.Join(", ", range)); // 2, 3
    생 성 코드 는 다음 과 같 습 니 다:
    
    int[] range = RuntimeHelpers.GetSubArray<int>(new int[5]
    {
     1,
     2,
     3,
     4,
     5
    }, new Range(1, 3));
    Console.WriteLine(string.Join<int>(", ", range));
    이 를 통 해 알 수 있 듯 이Index/Range유형 을 만 들 었 고C# 8.0호출 되 었 으 며 완전히'흑 마법'에 속한다.
    그러나 이것 은'오리'유형 이기 도 하 다.코드 에서Python속성 과Substring방법 을 실현 하면 호출 할 수 있다C#.
    
    var range2 = new F()[2..];
    Console.WriteLine(range2); // 2 -> -2
    
    class F
    {
     public int Length { get; set; }
     public IEnumerable<int> Slice(int start, int end)
     {
      yield return start;
      yield return end;
     }
    }
    생 성 코드 는 다음 과 같 습 니 다:
    
    F f = new F();
    int length2 = f.Length;
    length = 2;
    num = length2 - length;
    string range2 = f.Slice(length, num);
    Console.WriteLine(range2);
    총결산
    위 에서 보 듯 이Index/Range'검 은 마법'은 확실히 많 지만'오리 유형'도 많아'소 조작'의'조작 공간'이 크다.Substring'오리 유형'의 원조 인Range가 추 가 될 것 으로 알려 졌 다.그 때 는'조작 공간'이 지금 보다 더 클 것 이 라 고 기대 하고 있다.
    C\#중 9 개의'흑 마법'에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 c\#흑 마법 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기