내용 보기
작성자
관리자 (IP : 172.17.0.1)
날짜
2020-12-22 08:54
제목
[C#] .NET 코드 리뷰 팁, Task/Async/Await 사용 방법 등
1. NullReferenceException 관련 모음
List<Person> persons; ==> List<Person> persons = new List<Persons>();
public List<Person> GetPersons() { return new List<Person>(); }
List<int> numbers = new List<int> { };
int firstNumber = numbers.DefaultIfEmpty(1).First();
var firstPerson = persons.FirstOrDefault(x => x.Age > 18);
if (firstPerson != null)
{
// ...
}
var persons = new Dictionary<string, Person> = new Dictionary<string, Person>(); if (persons.ContainsKey("Jack")) { var person = persons["Jack"]; // ... } if (persons.TryGetValue("Jack", out Person person)) { // ... }
protected override void SetValueImpl(object target, SomeStatus value)
{
var ctrl = target as ControlA;
ctrl.Status = newValue;
}
if (target is ControlA) { var ctrl = target as ControlA; ctrl.Status = newValue; }
if (target is ControlA ctrl)
{
ctrl.Status = newValue;
}
A?.B?.Do(C); ==> if (A != null) { if (B != null) { B.Do(C); } }
string firstElement = (lines != null) ? lines[0] : null; ==> string firstElement = lines?[0];
class Counter
{
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
/*
if (ThresholdReached != null)
{
ThresholdReached(this, e);
}
*/
ThresholdReached?.Invoke(this, e);
}
}
int[] elems = null; int [] GetElements() { // return (elems != null) ? elems : Array.Empty<int>(); return elems ?? Array.Empty<int>(); } Dictionary
/* if (variable is null) { variable = expression; } */ variable ??= expression;
2. Task/Async/Await
async 메서드의 void 반환 타입 사용에 대하여 ; https://www.sysnet.pe.kr/2/0/11414
WebClient 타입의 ...Async 메서드 호출은 왜 await + 동기 호출 시 hang 현상이 발생할까요? ; https://www.sysnet.pe.kr/2/0/11419 C# - Task.Yield 사용법 (2) ; https://www.sysnet.pe.kr/2/0/12245
public async Task<string> GetDataFromApiAsync() { //Do some async jobs } /*? 이렇게 처리하는 것도 가능하지만, public async Task<string> GetDataAsync() { return await GetDataFromApiAsync(); } */ ? // Async 메서드의 Task를 직접 반환하는 것을 더 권장 public Task<string> GetDataAsync() { // Just return the task return GetDataFromApiAsync(); } 3. Task/Async/Await 사용 시 blocking 상황이 필요하다면?
// C# 9.0 - (15) 최상위 문(Top-level statements) using System; using System.Threading; using System.Threading.Tasks; Console.WriteLine(DateTime.Now); await TaskA(); await TaskB(); Console.WriteLine(DateTime.Now); Task TaskA() { return Task.Run(() => { Console.WriteLine("A work Started"); Thread.Sleep(2000); Console.WriteLine("A work Completed"); }); } Task TaskB() { return Task.Run(() => { Console.WriteLine("B work Started"); Thread.Sleep(2000); Console.WriteLine("B work Completed"); }); } /* 출력 결과 2020-12-17 오전 11:47:24 A work Started A work Completed B work Started B work Completed 2020-12-17 오전 11:47:28 */
Console.WriteLine(DateTime.Now); Task taskA = TaskA(); Task taskB = TaskB(); taskA.Wait(); taskB.Wait(); Console.WriteLine(DateTime.Now); /* 출력 결과 2020-12-17 오전 11:46:48 B work Started A work Started A work Completed B work Completed 2020-12-17 오전 11:46:50 */
Task.WaitAll(taskA, taskB);
/* 출력 결과
2020-12-17 오전 11:49:16
A work Started
B work Started
B work Completed
A work Completed
2020-12-17 오전 11:49:18
*/
await Task.WhenAll(taskA, taskB); /* 출력 결과 2020-12-17 오전 11:51:58 A work Started B work Started A work Completed B work Completed 2020-12-17 오전 11:52:00 */
WebClient 타입의 ...Async 메서드 호출은 왜 await + 동기 호출 시 hang 현상이 발생할까요? ; https://www.sysnet.pe.kr/2/0/11419
4. 예외 처리
File.Open("test.txt", FileMode.Open);
Unhandled exception. System.IO.FileNotFoundException: Could not find file 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt'.
File name: 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt'
at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
...[생략]...
using System;
using System.IO;
namespace ConsoleApp1
{
static class Program
{
static void Main()
{
try
{
ProcessFile();
}
catch (Exception)
{
throw;
}
}
private static void ProcessFile()
{
File.Open("test.txt", FileMode.Open);
}
}
}
Unhandled exception. System.IO.FileNotFoundException: Could not find file 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt'. File name: 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt' at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle) at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share) at System.IO.File.Open(String path, FileMode mode) at ConsoleApp1.Program.ProcessFile() in C:\ConsoleApp1\Program.cs:line 23 at ConsoleApp1.Program.Main() in C:\ConsoleApp1\Program.cs:line 13
try
{
ProcessFile();
}
catch (Exception ex)
{
throw ex;
}
Unhandled exception. System.IO.FileNotFoundException: Could not find file 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt'. File name: 'C:\ConsoleApp1\bin\Debug\net5.0\test.txt' at ConsoleApp1.Program.Main() in C:\ConsoleApp1\Program.cs:line 17
catch (Exception ex)
{
throw new MyException("error occurs", ex); // 이전 예외를 inner exception으로 연결
// throw new MyException("error occurs"); // 이전 예외 정보를 날리므로 좋지 않은 사례
}
5. HttpClient 관련 모음
HttpClient와 HttpClientHandler의 관계 ; https://www.sysnet.pe.kr/2/0/12024 C# - HttpClient에서의 ephemeral port 재사용 ; https://www.sysnet.pe.kr/2/0/12449
Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
InvalidOperation exception: The request message was already sent. Cannot send the same request message multiple times.
public static HttpRequestMessage Clone(this HttpRequestMessage req) { HttpRequestMessage clone = new HttpRequestMessage(req.Method, req.RequestUri); ? clone.Content = req.Content; clone.Version = req.Version; ? foreach (KeyValuePair<string, object> prop in req.Properties) { clone.Properties.Add(prop); } ? foreach (KeyValuePair<string, IEnumerable<string>> header in req.Headers) { clone.Headers.TryAddWithoutValidation(header.Key, header.Value); } ? return clone; }
6. Collection/List 관련
foreach (var item in ...)
{
await HandleItemAsync(item);
}
var files = container.ListBlobs(null, true, BlobListingDetails.None);// List all the files in the blob. It will return an IEnumerable object. foreach (var file in files) { await file.DeleteIfExistsAsync(); }
var files = container.ListBlobs(null, true, BlobListingDetails.None);// List all the files in the blob. It will return an IEnumerable object.
foreach (var file in files.ToList())
{
await file.DeleteIfExistsAsync();
}
IEnumerable<string> names = GetNames(); foreach (var name in names) Console.WriteLine("Found " + name); var allNames = new StringBuilder(); foreach (var name in names) allNames.Append(name + " ");
List<string> names = GetNames().ToList();
foreach (var name in names)
Console.WriteLine("Found " + name);
var allNames = new StringBuilder();
foreach (var name in names)
allNames.Append(name + " ");
7. 기타
== 연산자보다는 Equals 메서드의 호출이 더 권장됩니다. ; https://www.sysnet.pe.kr/2/0/2878
|
출처1
https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=12461
출처2