성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# 8.0의 Index/Range 연산자를 .NET Framework에서 사용하는 방법 및 비동기 스트림의 컴파일 방법</h1> <p> C# 8.0의 Index, Range 연산자는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > csharplang/proposals/csharp-8.0/ranges.md ; <a target='tab' href='https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md'>https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.md</a> </pre> <br /> C# 컴파일러에 의해 결국 System.Index와 System.Range 타입으로 변환됩니다. 문제는 이 타입들이 .NET Core 3.0의 System.Runtime에만 있다는 점입니다. (현재 2018-03-05 기준의 .NET Framework 4.8 preview에도 포함하고 있지 않습니다.) 따라서 기본 환경에서는 .NET Framework 프로젝트에서는 사용할 수 없는데요. 대신 우회 방법이 있습니다. 다름 아닌, 그냥 구현을 포함해 주면 됩니다. ^^<br /> <br /> 그래서 다음의 소스 코드에 있는 것을 그대로 포함시키고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > csharplang/proposals/csharp-8.0/ranges.cs ; <a target='tab' href='https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.cs'>https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/ranges.cs</a> </pre> <br /> Span 타입을 위해 System.Memory 어셈블리를 NuGet으로부터 추가해 주면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > PM> Install-Package System.Memory </pre> <br /> 다음과 같은 소스 코드가 정상적으로 빌드됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; // 2019-03-05 기준 C# 8.0 beta로 빌드 class Program { static void Main(string[] args) { string txt = "this"; Console.WriteLine(txt[^1]); Console.WriteLine(txt[^2]); Console.WriteLine(txt[^3]); { int i = 4; System.Index firstWord = ^i; Console.WriteLine(txt[firstWord]); } { System.Range full = 0..^0; string copy = txt[full]; Console.WriteLine(copy); } { string copy = txt[..]; Console.WriteLine(copy); Console.WriteLine(txt[..2]); Console.WriteLine(txt[1..]); } } } </pre> <br /> 물론, .NET Core 2.2 이하의 환경에서도 위와 같이 처리해 주면 C# 8.0의 Index/Range 연산자를 사용할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> C# 8.0의 비동기 스트림도 현재 타입을 구현하고 있는 어셈블리의 문제로 인해 .NET Core 3.0 대상의 프로젝트에서만 정상적으로 빌드가 됩니다. System.Index/System.Range와 마찬가지로 이것 역시 타입을 맞춰주면 빌드가 되는데 비동기 스트림의 인터페이스를 제외한 실질적인 구현을 담고 있는 System.Runtime.CompilerServices.AsyncIteratorMethodBuilder와 그 연관 타입들의 복잡함으로 간단하게 소스 코드를 붙여다 쓸 수 있는 상황이 아닙니다. 그래도 다음의 소스 코드만 포함하면,<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.Threading; using System.Threading.Tasks; namespace System.Collections.Generic { public interface <a target='tab' href='https://anthonychu.ca/post/async-streams-dotnet-core-3-iasyncenumerable/'>IAsyncEnumerable</a><out T> { IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default); } public interface IAsyncEnumerator<out T> : IAsyncDisposable { ValueTask<bool> MoveNextAsync(); T Current { get; } } } namespace System { public interface IAsyncDisposable { ValueTask DisposeAsync(); } } namespace System.Runtime.CompilerServices { public struct AsyncIteratorMethodBuilder { // Fields private AsyncTaskMethodBuilder _methodBuilder; // Methods public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { this._methodBuilder.AwaitOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine); } public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { this._methodBuilder.AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine); } public void Complete() { this._methodBuilder.SetResult(); } public static AsyncIteratorMethodBuilder Create() { return new AsyncIteratorMethodBuilder(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MoveNext<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { // AsyncMethodBuilderCore.Start<TStateMachine>(ref stateMachine); } // Properties /* internal object ObjectIdForDebugger { get { return this._methodBuilder.ObjectIdForDebugger; } } */ } } namespace System.Threading.Tasks.Sources { public struct ManualResetValueTaskSourceCore<TResult> { private TResult _result; private object _dummy; private int _dummyPrimitive; public bool RunContinuationsAsynchronously { get { throw null; } set { } } public short Version { get { throw null; } } public TResult GetResult(short token) { throw null; } public ValueTaskSourceStatus GetStatus(short token) { throw null; } public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { } public void Reset() { } public void SetException(Exception error) { } public void SetResult(TResult result) { } } } </pre> <br /> .NET Framework에서도 C# 8.0의 비동기 스트림 문법을 컴파일까지는 할 수 있습니다. (당연히 실행하면 예외가 발생하는데, 저 코드의 내부를 채워주면 정상 동작할 수 있습니다. ^^;)<br /> <br /> 혹시 저 내부 코드를 채운 NuGet 패키지를 알고 계시다면 덧글 부탁드립니다. ^^<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1422&boardid=331301885'>첨부 파일은 이 글의 예제 프로젝트를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7518
(왼쪽의 숫자를 입력해야 합니다.)