- ããã©ã¼ãã³ã¹ã«å½±é¿ã®å¤§ãã絶対ã«å®ãã¹ããã¨
- ç°å¢
- æ§é ä½
- ããã¯ã¹åãåé¿ãã
- ç¥ããªãéã«ä½ãããã¤ã³ã¹ã¿ã³ã¹ã«æ°ãé ã
- æéã¨ãªã½ã¼ã¹ãæå¹ã«ä½¿ã
- åè
ãã®è¨äºã¯ãC# Advent Calendar 2024ãã«åå ãã¦ãã¾ããã·ãªã¼ãºï¼ã®ï¼ï¼æï¼ï¼æ¥ã®å 容ã§ãã
C# ã®ããã©ã¼ãã³ã¹é«éåã«é¢ãããã¨ãå¦ç¿ããå 容ã§ããä¸è¨ã®ãã㪠Tips ããã£ãã®ã§ãå人çã«ãµã³ãã«ã³ã¼ããæ¸ããã調ã¹ãããã¦å¦ç¿ããå 容ã«ãªãã¾ããï¼å 容ã¯å çããæªè¨è¼ãããï¼
ãã¤ã³ãã¯ãã½ããã¦ã§ã¢ã¯éãã¦å°ããã¨ã¯ãªãã
- ãã¼ãã¢ãã±ã¼ã·ã§ã³ï¼å²ãå½ã¦ï¼ãï¼é¿ãããã¨ããã¯ï¼é¿ãã
- ã¡ã¢ãªã®åå©ç¨ã¨ã¹ã¿ãã¯é åã®æ´»ç¨ãå¾¹åº
- éåæ I/O ã使ã
- CPU ã¯é«ä¾¡ãªãªã½ã¼ã¹ãªã®ã§ãå¾ ã¡æéãä¸ãã使ãåã
- è¨ç®å¹çãä¸ãã
- é«å¹çã¢ã«ã´ãªãºã ã§åä½æéãããã®è¨ç®åæ°ãå¢ãã
C# ã«ãããã¡ã¢ãªç®¡çæ¹æ³ã¯å¤åãã¹ã¿ãã¯ãã¨åç §åããã¼ããã®ï¼ç¨®é¡ãããã¾ããä¸è¬çã«ãã¼ãã®é åã® "確ä¿" ã¯ã¹ã¿ãã¯ã¨æ¯ã¹ãã¨éããå¦çã«ãªãã¾ãã
å¥ã®è¨ãæ¹ã§ã®ãã¤ã³ãï¼
- å®è£
æãããããã¨ãã£ã¦æããªã
- ããéãã³ã¼ããã¹/å ±éã©ã¤ãã©ãªã¯ç¹ã«ç®ãåãã
- éãã³ã¼ããæ¸ãçãã¤ãã
- ç·´ç¿ã¨æã£ã¦åãçµãã»ãããã
èªãã¨ãã®ããã®ç¨èªã¡ã¢ï¼
å¤åã®å©ç¹ã¯ãã¹ã¿ãã¯ã«å¤ãç½®ãï¼ãã¼ãã使ããªãï¼ãã¨ã«ããæ§è½åä¸ã§ããããã¯ã¹åï¼ãã¼ãé åã®ç¢ºä¿ï¼ãèµ·ããã¨ãå¤åã®å©ç¹ã¯å¤±ããã¾ãã
ããã©ã¼ãã³ã¹ã«å½±é¿ã®å¤§ãã絶対ã«å®ãã¹ããã¨
ã³ã¬ã¯ã·ã§ã³ã®åããã
List åãé ååã«å¤æãããä¸å¯é¿ãªçç±ããªããªãç¡é§ãªã¡ã¢ãªã³ãã¼ãçºçããããé©åã§ã¯ãªãã
List<int> values = [1, 2, 3, 4]; DoSomething(values.ToArray()); void DoSomething(int[] values) { ... }
ãã ããå¾è¿°ã® AsSpan()
ï¼Span<T>
ï¼ã¯ãéã«æé©åã«ãªããã¨ãããã¾ãã
int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; foreach (var i in array.AsSpan()[2..6])) { ... }
ã«ã¼ãå ã®ç·å½¢æ¢ç´¢
ã³ã¬ã¯ã·ã§ã³ã®ãã¼ã¿æ°ãèãã¦ããããããã¼ã¿ãããã¨ãã¯ã©ãããã°åå¾ãéãã®ããFirst ã¯ç·å½¢æ¢ç´¢ãªã®ã§å¹çã¨ããããªãããã
foreach (var sample in samples) { // BAD var bad = sample.First(p => p.id == id); // GOOD var good = sample[id]; }
ç·å½¢æ¢ç´¢â¦â¦å é ããé çªã«æ¯è¼ãè¡ããè¦ã¤ããã°çµäºããã
ã³ã¬ã¯ã·ã§ã³ã®åæ容éãæå®
åçãªãããã¡æ¡å¼µã¯ããªãã¹ãé¿ããã
åæ容é (capacity) ãæå®ããªããã°ãæå¾ã®è¦ç´ ã追å ããã¨ãã«ï¼åã®å é¨ãããã¡ç¢ºä¿ã¨å ¨è¦ç´ ã®ã³ãã¼ãçºçããããéå¹çã
ããã©ã¼ãã³ã¹ã«æªå½±é¿ãããã®ã¯ã Count 3 ã®ã¿ã¤ãã³ã°ãã³ã¬ã¯ã·ã§ã³ã®å®¹éãä¸ããããã«ãæ¢åã³ã¬ã¯ã·ã§ã³ããæ°ããã³ã¬ã¯ã·ã§ã³ã«ã³ãã¼ãçºçããã
int[] values = [1, 2, 3, 4]; var list = new List<int>(capacity: values.Length / 2); foreach (var x in values) { list.Add(x); Console.WriteLine($"Capacity: {list.Capacity}, Count: {list.Count}"); }
Capacity: 2, Count: 1 Capacity: 2, Count: 2 Capacity: 4, Count: 3 Capacity: 4, Count: 4
Result 㨠Wait ã¯ããã
ã¹ã¬ããã®å¦çããããã¯ããã®ã§ãã¹ã¬ãããå æããããæ³åãã¦ããããããããããã¯ããããã
çµæçã«ãªã½ã¼ã¹å¹çãä½ä¸ããã
public int DoBadSomething() { var result = CallAsync().Result; return result + 1; } public async Task<int> DoGoodSomething() { var result = await CallAsync(); return result + 1; }
æ¬è³ªçã§ã¯ãªããã©ããããããã¯ãé¿ãã対çã®ä¸ä¾ãå¦çããã¹ã¬ãããå¤ãã¦å¾ ã¤ãã©ãã¹ã¬ãããå¹ççã«å©ç¨ããã¦ããã¨ã¯è¨ããªãã
public int DoBadSomethingSafe() { var result = CallAsync().ConfigureAwait(false).GetAwaiter().GetResult(); return result + 1; }
ç°å¢
æéã®éçº/å®è¡ç°å¢
ææ°ã® .NET ãå©ç¨ãã¦ãããã¨ã
.NET Framework ãããä½åãéããC# 7.x 以éã¯ãããã©ã¼ãã³ã¹ãæèããæ¹åãå¤ããåºæ¬çã«ã¯å¾æ¹äºæãããã®ã§æ´æ°ãã¦ææ°ã®è¨èªæ©è½ã使ãã
- MemoryPack
- MessagePack for C#
- FastEnum
æ§é ä½
æ§é ä½ã®åªä½æ§
ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®é »åº¦ãä¸ãã
- GC ã®å®è¡æã¯ããã©ã¼ãã³ã¹ãç¬éçã«å¤§ããä½ä¸ãã
- ç¹ã« Unity ã®ãããªãã¬ã¼ã ãã¼ã¹ã®ã¢ããªã¯æ°ãã¤ãã
ã¡ã³ãã¼ã¸ã®ã¢ã¯ã»ã¹ãé«éã«ãªã
- å¤åï¼ã¹ã¿ãã¯é åã«ããã®ã§ããã®ã¾ã¾ç´ã«ã¢ã¯ã»ã¹å¯è½
- åç §åï¼ãã¼ãé åããå¤ããã©ã£ã¦ã¢ã¯ã»ã¹ãã
æã£ããããæ§é ä½ã®æåã¯ãè¨èªä»æ§ã®ç¥èãå¿ è¦ãªã¨ãããããã¾ããããã¤ãã®ä½æ³ãç¥ã£ã¦ãããã¨ã§ãå¹çåãããæãã§ãã
æ§é ä½ã®æ¬ ç¹
é«é »åº¦ã§å¤ã®ã³ãã¼ãçºçãã
- å¼æ°/æ»ãå¤/å¤æ°ã¸ã®ä»£å ¥/é¢æ°å¼ã³åºã
- ãµã¤ãºã®å¤§ããæ§é ä½ã®å ´åã¯ãéã«ã³ã¹ãã«ãªãï¼16 bytes ç®éï¼
ç¶æ¿/å¤æ ãã§ããªã
- ç¾ç¶ã¯ interface + æ¡å¼µã¡ã½ãããé§ä½¿ãã
ã¤ã³ã¿ã¼ãã§ã¼ã¹ä»¥å¤ã®ç¶æ¿ãã§ããªãçç±ãèããã¨ãstruct ã¯ãã¡ã¢ãªããããã³ã°ããæ§é ã ãããã¨ããèãæ¹ãããããããã¨æãã¾ããè£ä»ãã¨ãã¦
StructLayout
ã¯ããã©ã«ãã 㨠Sequential ã§ããï¼class ã®ããã«ï¼ãã¼ã¿ã®ä¸¦ã³ãã¢ã©ã¤ã¡ã³ãã«ããããæé©åã¯ããã¾ãããå¤åã¨ãã¦ãåºå®ãµã¤ãºãå®ããã¨ãåªå ãããã¨èãããã¨ãã§ãã¾ãã
ã¤ã³ã¿ã¼ãã§ã¼ã¹ãä»ä¸ã§ããã®ã¯ãã¡ã¢ãªæ§é ã«å½±é¿ãä¸ããã«å¤æ§æ§ã追å ããã ãã ããã§ãããã¨ãã¨ãï¼£è¨èªã®æ§é ä½ã¯å®å ¨ãªå¤åã§ã¡ã½ãããä½ããã¨ãã§ãã¾ããã§ãããããããï¼£ï¼ã®æ§é ä½ã¯æåãããå¤åã¨ãã¦ã®ç¹æ§ãæã¡ã¤ã¤ã¡ã½ãããæã¦ã¾ããåãçç±ã ã¨èãã¦ãã¾ãã
åç §æ¸¡ã
æ§è½å£åã«ç´çµããã³ãã¼ãæå¶ãããæ§é ä½ã®ãµã¤ãºã大ããã¨ãã¯æ¤è¨ããã
å
·ä½çã«ããã¨ä»¥ä¸ã®ä¾ã 㨠a
㯠PassThrough
ã¡ã½ããã«åç
§ã渡ãã¦ã㦠a
ã®ã¡ã¢ãªä¸ã®ã¢ãã¬ã¹ãå
±æãããåãã«ãªãã¾ãã
ããã« ref var b
㯠a
ãåç
§ãã¦ãããã a
㨠b
ã¯åãå¤ã§ãããb
ãå¤æ´ãã㨠a
ã®å¤ãæ¸ãæããã
private void TestRef() { var a = 1; ref var b = ref PassThrough(ref a); // b ãå¤æ´ãã㨠a ã«ãå½±é¿ãã b = 2; Console.WriteLine(a); // output 2 } private ref int PassThrough(ref int b) { ref var c = ref b; return ref c; }
ref æ»ãå¤ã¯ C# 7.2 ããå©ç¨å¯è½ã«ãªã£ãã®ã§ 2017 å¹´æ«ããã®æ©è½ã§ããã¾ã ref readonly
ã®ãããªæ»ãå¤ã®æ¸ãæ¹ãã§ãããï¼ããå¾è¿°ã®ããã«ããã©ã¼ãã³ã¹ã®è¦³ç¹ã§ã¯æ³¨æãå¿
è¦ï¼
ãã®ã»ãã«ããåç
§æ¸¡ãã ãã©èªã¿åãå°ç¨ããªã in
ã使ããã®ã§ã大ããæ§é ä½ã渡ãã¨ãã¯ããã©ã¼ãã³ã¹æ¹åã«ã¤ãªããå¼æ°ã®æå®ã«ãªãã
å¾æ¥ã® out
ã¯ãåç
§æ¸¡ãããããã¡ã½ããã®ä¸ã§ãã¡ã½ããå¤ã®å¤æ°ã®å¤ãæ¸ãæãããã¨ãã§ããã®ã«å¯¾ã㦠in
ã¯ãå
¥åç¨ããæ示ãã¾ãã
ã³ã³ãã¤ã©ã®åä½ã¨ãã¦ã¯ in/out 㯠ref ãªã®ã§ãå¼æ°éãã®ãªã¼ãã¼ãã¼ãã¯ã§ããªãã
è£è¶³ã¨ãã¦ãæ§é ä½ã§ã¯ãªãã¯ã©ã¹ã®å ´åã¯ãã¾ãããã©ã¼ãã³ã¹ã®æ¹åã«å¹æããªããçç±ã¯åç §åãªã®ã§ãã¤ã³ã¿ã®ãããªåãããããã¼ãé åãå©ç¨ãã¦ããããããã¼ã¿ãã®ãã®ãã³ãã¼ããããã¨ããªãã
ref readonly/in ã®é£ãã
Defensive Copy ãçºçãã¦ãã¾ãã
å¼æ°ã®å ´å㯠in
ã§ãæ»ãå¤ã®å ´å㯠ref readonly
ã¨ãã¦ããã®åé¡ãã©ã¡ãã®å ´åã§ãçºçãã¦ãã¾ããï¼å¾è¿°ã® Generics ã¯å¥ï¼
ããã°ã©ã ã®é½åã¨ãã¦ãå¼ã³åºãå´ã¯ãã¡ã½ããã®å é¨ã§å¤ãæ¸ãæãã£ã¦ããªããã¨ãä¿è¨¼ããæ¹æ³ãæããªãã®ã§ããããããã¡ã½ãããå¼ãã æç¹ã§ç¡æ¡ä»¶ã«ã³ãã¼ãä½ã£ã¦ãã¾ãåãã®ãã¨ã Defensive Copy ã¨ããã
対çï¼
- æ§é ä½ã readonly ã«ãã¦ãã
- é¢æ°å ã§ãã£ã¼ã«ãã®æ¸ãæãããªããã¨ãä¿è¨¼ãã¦ãã
readonly struct ReadOnly { public readonly int X; } struct Foo { .. public readonly int Add() => X + Y; // GOOD public int Sub() => X - Y; // BAD ã³ãã¼çºç .. }
ã³ãã¼æå¶
æ§é ä½ã®æ¡å¼µã¡ã½ãããä½ãã¨ãã¯ãåç §æ¸¡ãã«ãããGenerics ã«ããã in å¼æ°ã¯ã§ããªãã
ããã¯ã³ã³ãã¤ã©ãåã¯å¤åãåç §åããå¤æã§ãã¦ããªãã®ã§ãä»æ§ã¨ã㦠in å¼æ°ã«ã§ããªããï¼åç §åã®ã¨ãã¯åç §æ¸¡ãã§ããå¿ è¦ããªãï¼
static void Process<T>(in this T data) // ã¨ã©ã¼ { } static void Process<T>(ref this T data) : where T : struct // OK { }
in ã使ã£ã overload ãããã¨ãããstruct èªä½ã readonly ã«ãã¦ããã
readonly struct Complex { public double R { get; } public double I { get; } // in å¼æ°ãèªããããããã«ãªã£ã public static Complex operator +(in Complex x, in Complex y) => new Complex(x.R + y.R, x.I + y.I); }
ã¨ãããããåºæ¬çã«ã¯ in 㯠readonly 㪠struct ã«ä½¿ããã®ãã¨ããèãæ¹ã«ãªãã¯ãã
ValueTuple
å¿ååã®æ´å²ã¿ãããªãã®ãLINQ ã¨ãã£ãå±æçãªã¨ããã§ä½¿ãã¨ãããã®ãValueTuple ã¯ãå¤ãå¤æ´ã§ããæ§é ä½ã¨ãã¦èãã¦ããã
ã³ã¬ã¯ã·ã§ã³ããã³ã¬ã¯ã·ã§ã³ãé¸æããåä½ãªãããValueTuple ã¯ãã¼ãã使ããªãããããããããã©ã¼ãã³ã¹ä¸ã®ç¸æ§ãããè¨è¨ã ã¨æãã
// ValueTuple : ã¹ã¿ãã¯å©ç¨ var q1 = collection.Select(x => (value: x, power: x * x)); // å¿åå: ãã¼ãå©ç¨ var q2 = collection.Select(x => new { Value = x, Power = x * x }); // Tuple : ãã¼ãå©ç¨ï¼ååãä»ããããªãï¼ var q3 = collection.Select(x => Tuple.Create(x, x * x));
Span
é£ç¶ããã¡ã¢ãªé åãç´æ¥åç §ã§ãããunsafe ãããªã managed ãªç¶æ ã§ã¢ã¯ã»ã¹ã§ãããé åãæååãããã¡ã¢ãªã®å確ä¿ãããªãé¨åçãªåç §ãã§ããã
const string text = âab123cdâ; var span = text.AsSpan(2, 3); var sub = text.Substring(2, 3); // 123
ä¸èº«ã read ããã ããªã span ãä¸æãæ´»ç¨ãããã¨ã§ãç¡é§ãªã³ãã¼ãé¿ãã¦é«éåããããã¨ãã§ããã
ã§ããå é¨çã«ã³ãã¼ãçºçãã¦ãããã©ãããªãã¦ãè¨èªã®ç解ãæ·±ã¾ããªãã¨æé©åã§ããªãã
string.Create
string.Create 㯠Span
以ä¸ã¯ byte
åã®å¤ãæååã«å¤æããï¼ä¾ãã°ãæåå "01101100" ã«ããï¼ãã®ã§ buffer ã span ãªã®ã§ StringBuilder ã®ãããªä¸éå¤æ°ãåå¨ããªããã¨ã¦ããã¯ãã«ã«ãªæè¡ã ã¨æã£ãã
static string ToBitString(byte value) => string.Create(8, value, (buffer, state) => { const byte on = 0b_0000_0001; for (var i = 0; i < buffer.Length; i++) { buffer[buffer.Length - 1 - i] = ((state >> i & on) == on) ? '1' : '0'; } });
ããã¯ã¹åãåé¿ãã
å¤ãç£å»ã使ã£ã¦ã¯ãããªã
- System.Collections
- ãã¡çµ¶å¯¾
- System.Collections.Generics
- å¤æ´å
é generics ã³ã¬ã¯ã·ã§ã³ãªã®ã§ä½¿ããªãã»ãããããåå空éãåºã¦ããã注æããã»ããããã
System.Enum ã®åé¡ç¹
å¤ãä»£å ¥ããã¨ããã¯ã¹åãã¦ãã¾ãã
// ããã¯ã¹åãã static void Foo(Enum value) {} // Generics å¶ç´ãããã¨ããã¯ã¹åããªã static void Foo<T>(T value) where T : struct, Enum {}
æ§é ä½ã interface åã¨ãã¦æ±ã
æ£ç´ãæ§é ä½ã®é«éåãã¯ããã¯ã¯ããã¢ãã¯ã ã¨æãã
struct 㯠object ãããã¤ã³ãã¨ãã¦ã¤ã³ã¿ã¼ãã§ã¼ã¹ãçµç±ãã㨠Box åãçºçãã¦ãã¾ãããããã㧠generics ã使ãã¨è±ä»®æ³åã«ãªãã
// å¼æ°ã§box åãçºçãã¦é ã static void Interface(IDisposable x) => x.Dispose(); // .NET Core 2.1 以éã®å ´å // è±ä»®æ³åã¨ããæé©åãããã static void NonGeneric(X x) => ((IDisposable)x).Dispose(); // å®å®ãã¦é«é static void Generic<T>(T x) where T : IDisposable => x.Dispose();
ä¸çªããè¨ããããããªã®ããæ¯è¼ã® equal é¢ä¿ãªã®ã§ããããã£ãã¨ãã㯠record ã使ããã¨ã§ãåé¿ã§ããã¨æãã¾ãã
ç¥ããªãéã«ä½ãããã¤ã³ã¹ã¿ã³ã¹ã«æ°ãé ã
ã¯ãã¼ã¸ã£ã®å¤æ°çæ
å¤æ°ã®ãã£ããã£ã¼ãï¼ãé ãã¯ã©ã¹ã®çæã¨ãããã¨ã«ãªãã¾ãããªã®ã§ããã¼ã確ä¿ã¨å©ä¾¿æ§ã¯ãã¬ã¼ããªãã®é¢ä¿ã§ãã
å ·ä½çã«ã¯ãã©ã ãå¼ãå¿åã¡ã½ããå ã§å¤é¨ã¹ã³ã¼ãã®å¤æ°ãåç §ããã¨ããå¤æ°ãã¯ãã¼ã¸ã£ã«ãã£ããã£ããããã¨ãæãã¦ãã¾ãããã®ãã¯ãã¼ã¸ã£ãã¯ãã¼ãä¸ã«ãªãã¸ã§ã¯ãã¨ãã¦çæããããã¨ã«ãªãã¾ãã
以ä¸ã¯ id ããã£ããã£ãããä¾ã§ããVisual Studio ã§ã¯ "=>" ã®é¨åã«ã«ã¼ã½ã«ãåãããã¨ããã£ããã£ããã¦ãããã©ããããç¥ããã¨ãã§ãã¾ãã
static async Task<Person> GetAsync(int id) { var people = await QueryFromDbAsync(); return people.FirstOrDefault(x => x.Id == id); }
ãªã®ã§ããã£ã«ã¿ãªã³ã°é¨åæ¡ä»¶ãã©ã ãå¼ã®å¤ã«ç½®ããæ¡å¼µã¡ã½ããã«ãã¦èªä½ãããããããã¨ã«ãªãã
static async Task<Person> GetAsync(int id) { var people = await QueryFromDbAsync(); foreach (var person in people) { if (person.Id == id) return person; } return null; }
public static T? FirstOrDefault<T, TState>( this IEnumerable<T> source, TState state, Func<T, TState, bool> predicate) { foreach (var x in source) { if (predicate(x, state)) return x; } return default; }
ã¾ããã©ã ãå¼ãå¿åã¡ã½ããã¯å¤ã®å¤æ°ããã£ããã£ã§ãã¦ãã¾ããããå¤æ°åã¨ã㦠x ã y ã i ã使ã£ãã¤ããããå¤ã®å¤æ°ããã£ããã£ãã¦ãã¾ã£ã¦ãã°ã«ãªããã¨ãããã¾ããããããã¨ãã¯ãéçã©ã ãå¼ã使ããã¨ã§ãå¤é¨ã¹ã³ã¼ãã®å¤æ°ãå ¥ãè¾¼ã¾ãªãããã«ï¼ãã種ï¼æ示ãããã¨ã«ãªãã¾ãã
var x = 10; var result = Enumerable.Range(0, 10) .Where(static x => x % 2 is 0) .ToDictionary(static x => x, static y => x * x); // è¦åã«ãªã
æéã¨ãªã½ã¼ã¹ãæå¹ã«ä½¿ã
éåæ IO ã使ã
await ãã¦ããéã«ã§ãããã¨ãããã
// ãããªãéä¿¡å¾ ã¡ãå¥å¦çã«æå¹æ´»ç¨ã§ãã var url = "...."; var client = new HttpClient(); var rss = await client.GetStringAsync(url); var node = XElement.Parse(rss);
並åå¦ç
ããããã®å¦çãç¬ç«ãã¦ãããªããParallel ã«ããã¨å¦çæéãç縮ã§ããããã
var t1 = LoadFile1Async(); var t2 = LoadFile2Async(); var t3 = LoadFile3Async(); await Task.WhenAll(t1, t2, t3);
ãã£ãã·ã³ã°
ã¾ãèãæ¹ã¨ã㦠Enum.GetValues ã¯ãªãã¬ã¯ã·ã§ã³ãå é¨çã«å©ç¨ãã¦ãããããæ¯è¼çã³ã¹ãã大ããæä½ã«ãªã£ã¦ãã¾ãã
ãªã®ã§ããã®å¦çãç¹°ãè¿ãå®è¡ãããã¨ã¯é¿ããããããã§ããã£ãã·ã³ã°ãå©ç¨ãããã¨ã§ãä¸åº¦ã ãå¤ãåå¾ãã¦ã以éã¯ä¿åãããå¤ã使ããã¨ã§ããã©ã¼ãã³ã¹ãä¸ããã
public static class FastEnum { public static IReadOnlyList<T> GetValues<T>() where T : struct, Enum => Cache<T>.Values; // ãã£ãã·ã¥ãç´æ¥åç § // éç Generics åã®ãã£ã¼ã«ãã«ãã£ãã·ã¥ãæ㤠private static class Cache<T> where T : struct, Enum { public static readonly T[] Values; static Cache() => Values = (T[])Enum.GetValues(typeof(T)); } }
ãã ãããã£ãã·ã¥ãããµã¤ãºã大ãããªãã¨ã¡ã¢ãªæ¶è²»ã大ãããªãããã£ãã·ã¥ãããå¤ãå¤æ´ãããå ´åãããã¨ããã£ãã·ã¥ã®ç¡å¹åãæ´æ°ãå¿ è¦ã«ãªãã®ã§ãããªãã
List ã®é«éã¤ãã¬ã¼ã·ã§ã³
ã³ã¬ã¯ã·ã§ã³ã®ãã¼ã¿ã Add/Remove/Clear ãªã©ã®æä½ãããã«ã大éã®ãã¼ã¿ã«ã¢ã¯ã»ã¹ããå ´é¢ã§ã¯ Span ãæå¹ãªãã¨ãããããªã¹ããå¤æ´ããªããã¨ã¯éè¦ã
List<int> list = [0, 1, 2, 3, 4]; var span = CollectionsMarshal.AsSpan(list); foreach (var x in span) { // Do something with x }
Frozen Collections
Frozen Collection ã¯ã³ã¬ã¯ã·ã§ã³ãä½æããå¾ã¯å¤æ´ãã§ãã¾ãããã¹ã¬ããã»ã¼ãã§ãã«ãã¹ã¬ããç°å¢ã§å®å ¨ã«å©ç¨ã§ããã®ãç¹å¾´ã
ãã¼ã¿ãåºå®åããããã¨ã§ãæ¤ç´¢ãæé©åããã¦ãã¾ããContains ãªã©ãé«éåã
åç´ãªãã¨ãªã®ã§ãFrozen ã§ãããã¨ãè¦ãã¦ããã° OK ã ã¨æãã¾ãã
var data = new Dictionary<int, string> { { 1, "One" }, { 2, "Two" }, { 3, "Three" }, }; var frozenData = data.ToFrozenDictionary();
æ§é ä½ã¯ yield return ããªã
ãããããããæ§é ä½ãå©ç¨ãããã¨ã§ãã¼ãã¢ãã±ã¼ã·ã§ã³ãåé¿ãããã¯ããã¯ã ã¨æãã¾ããå¤åãªã®ã§ããã£ãã·ã¥å¹çãæãã£ã¦ãé »ç¹ãªã¤ãã¬ã¼ã·ã§ã³é¨åã§æ§è½ãåä¸ããããã¯ããã¯ã®ã¯ãã§ãã
foreach ã LINQ 㯠GetEnumerator ã使ã£ã¦ã¤ãã¬ã¼ã·ã§ã³ãéå§ããã®ã§ãæ§é ä½ãè¿ãããã¨ãã¯ãããã¾ã§ã®ä¾ã®ããã«ã¤ã³ã¿ã¼ãã§ã¼ã¹å IEnumerator<T>
ã¨ãã¦æ±ãããã¨ãæé»çã«ãã¯ã·ã³ã°ãçºçããå¹çã®æªããããã
yield return ã¯ç¶æ ãã·ã³ãªã®ã§è¨ããã¨ããã¨ããã¯åãã¯ãã
class Program { static void Main() { var range = new RangeEnumerable(1, 10); foreach (var num in range) { Console.WriteLine(num); } } }
public struct RangeEnumerable : IEnumerable<int> { private readonly int _start; private readonly int _end; public RangeEnumerable(int start, int end) { _start = start; _end = end; } public Enumerator GetEnumerator() => new Enumerator(_start, _end); // æ示çã« IEnumerator<int> ã使ãããå ´å IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); // å é¨æ§é ä½ã§ IEnumerator<int> ãå®è£ public struct Enumerator : IEnumerator<int> { private readonly int _end; private int _current; public Enumerator(int start, int end) { _current = start - 1; _end = end; } public int Current => _current; object IEnumerator.Current => Current; public bool MoveNext() { if (_current < _end) { _current++; return true; } return false; } public void Reset() => throw new NotSupportedException(); public void Dispose(){} } }
è£è¶³ï¼C# ã®ã³ã³ãã¤ã©ã¯ãç¹å®ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹åãç´æ¥æå®ããªãã¦ãã対å¿ããã¡ã½ãããããããã£ãåå¨ãã¦ããã°ãã³ã¼ããæ£ããåä½ããã¾ããããã¯åãå³å¯ã«ã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ãã¦ããå¿ è¦ãç¡ãã¨ããç¹ã§ "duck typing" ã¨å¼ã°ãããã®ã§ãã