Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã¿ãŒã³ ãããã³ã° - ãã¿ãŒã³å ã®
isåŒãswitch ã¹ããŒãã¡ã³ããããã³ switch åŒã䜿çšããŠãä»»æã®æ°ã®ç¹æ§ã«å¯ŸããŠå
¥ååŒãç
§åããŸãã C# ã¯ã宣èšãåã宿°ããªã¬ãŒã·ã§ãã«ãããããã£ããªã¹ããvarãç Žæ£ãªã©ãè€æ°ã®ãã¿ãŒã³ããµããŒãããŠããŸãã ããŒã«åã®ããžã㯠ããŒã¯ãŒã andã orãããã³ notã䜿çšããŠããã¿ãŒã³ãçµã¿åãããããšãã§ããŸãã
C# èšèªãªãã¡ã¬ã³ã¹ã«ã¯ãC# èšèªã®ææ°ãªãªãŒã¹ ããŒãžã§ã³ãèšèŒãããŠããŸãã ãŸããä»åŸã®èšèªãªãªãŒã¹ã®ãããªã㯠ãã¬ãã¥ãŒã®æ©èœã«é¢ããåæããã¥ã¡ã³ããå«ãŸããŠããŸãã
ãã®ããã¥ã¡ã³ãã§ã¯ãèšèªã®æåŸã® 3 ã€ã®ããŒãžã§ã³ãŸãã¯çŸåšã®ãããªã㯠ãã¬ãã¥ãŒã§æåã«å°å ¥ãããæ©èœãç¹å®ããŸãã
ãã³ã
C# ã§æ©èœãåããŠå°å ¥ãããææã確èªããã«ã¯ã C# èšèªããŒãžã§ã³å±¥æŽã«é¢ããèšäºãåç §ããŠãã ããã
次㮠C# åŒããã³ã¹ããŒãã¡ã³ãã§ã¯ããã¿ãŒã³ ãããã³ã°ããµããŒããããŠããŸãã
ãããã®æ§é äœã§ã¯ãå ¥ååŒã次ã®ä»»æã®ãã¿ãŒã³ãšäžèŽãããããšãã§ããŸãã
- 宣èšãã¿ãŒã³: åŒã®å®è¡æã®åã確èªããäžèŽãæåããå Žåã¯ã宣èšããã倿°ã«åŒã®çµæãå²ãåœãŠãŸãã
- åãã¿ãŒã³: åŒã®å®è¡æã®åã確èªããŸãã
- 宿°ãã¿ãŒã³: åŒã®çµæãæå®ãã宿°ãšçããããšããã¹ãããŸãã
- ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³: åŒã®çµæãæå®ãã宿°ãšæ¯èŒããŸãã
- è«çãã¿ãŒã³: åŒããã¿ãŒã³ã®è«ççãªçµã¿åãããšäžèŽããããšããã¹ãããŸãã
- ãããã㣠ãã¿ãŒã³: åŒã®ããããã£ãŸãã¯ãã£ãŒã«ããå ¥ãåã«ãªã£ããã¿ãŒã³ãšäžèŽããããšããã¹ãããŸãã
- äœçœ®æå®ãã¿ãŒã³: åŒã®çµæãåè§£ããçµæã®å€ãå ¥ãåã«ãªã£ããã¿ãŒã³ãšäžèŽãããã©ããããã¹ãããŸãã
-
varãã¿ãŒã³: ä»»æã®åŒãšäžèŽãããã®çµæã宣èšããã倿°ã«å²ãåœãŠãŸãã - ç Žæ£ãã¿ãŒã³: ä»»æã®åŒãšäžèŽããŸãã
- ãªã¹ã ãã¿ãŒã³: èŠçŽ ã®ã·ãŒã±ã³ã¹ãã察å¿ããå ¥ãåã«ãªã£ããã¿ãŒã³ãšäžèŽããããšããã¹ãããŸãã
è«çãããããã£ãäœçœ®æå®ãããã³ãªã¹ã ãã¿ãŒã³ã¯ ''ååž°çãª'' ãã¿ãŒã³ã§ãã ã€ãŸãããããã«ã¯å ¥ãåã«ãªã£ããã¿ãŒã³ãå«ããããšãã§ããŸãã
ãããã®ãã¿ãŒã³ã䜿çšããŠããŒã¿ ããªãã³ ã¢ã«ãŽãªãºã ãæ§ç¯ããæ¹æ³ã®äŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: ãã¿ãŒã³ ãããã³ã°ã䜿çšããŠã¢ã«ãŽãªãºã ãæ§ç¯ããããåç §ããŠãã ããã
宣èšãã¿ãŒã³ãšåãã¿ãŒã³
宣èšãšåãã¿ãŒã³ã䜿çšããŠãåŒã®å®è¡æã®åãç¹å®ã®åãšäºææ§ããããã©ããã確èªããŸãã 宣èšãã¿ãŒã³ã䜿çšãããšãæ°ããããŒã«ã«å€æ°ã宣èšããããšãã§ããŸãã 宣èšãã¿ãŒã³ãåŒãšäžèŽãããšã次ã®äŸã«ç€ºãããã«ã倿ãããåŒã®çµæã«å€æ°ãå²ãåœãŠãããŸãã
object greeting = "Hello, World!";
if (greeting is string message)
{
Console.WriteLine(message.ToLower()); // output: hello, world!
}
åŒã®çµæã null 以å€ã§ã次ã®ããããã®æ¡ä»¶ãæºããããŠããå Žåã«ã åã®TãåŒã«äžèŽããŸãã
- åŒã®çµæã®å®è¡æã®åã«ã¯ã
Tãžã® ID 倿ããããŸãã -
Tåã¯ref structåã§ãããåŒããTãžã® ID 倿ããããŸãã - åŒã®çµæã®ã©ã³ã¿ã€ã åã¯
TåããæŽŸçããããã€ã³ã¿ãŒãã§ã€ã¹Tãå®è£ ãããããŸãã¯ããããã ãžã®Tãå¥ã«ååšããŸãã ãã®æ¡ä»¶ã§ã¯ãç¶æ¿é¢ä¿ãšã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ã«ã€ããŠèª¬æããŸãã æ¬¡ã®äŸã¯ããã®æ¡ä»¶ãæºããããŠããå Žåã® 2 ã€ã®ã±ãŒã¹ã瀺ããŠããŸãã
åã®äŸã§ã¯ãvar numbers = new int[] { 10, 20, 30 }; Console.WriteLine(GetSourceLabel(numbers)); // output: 1 var letters = new List<char> { 'a', 'b', 'c', 'd' }; Console.WriteLine(GetSourceLabel(letters)); // output: 2 static int GetSourceLabel<T>(IEnumerable<T> source) => source switch { Array array => 1, ICollection<T> collection => 2, _ => 3, };GetSourceLabelã¡ãœãããžã®æåã®åŒã³åºãã§ãåŒæ° ã®ã©ã³ã¿ã€ã åint[]ã Array åããæŽŸçããŠãããããæåã®ãã¿ãŒã³ãåŒæ°å€ãšäžèŽããŸããGetSourceLabelã¡ãœãããžã® 2 ã€ç®ã®åŒã³åºãã§ã¯ãåŒæ°ã®ã©ã³ã¿ã€ã å List<T> ã¯ãArray åããæŽŸçããŠããŸããããICollection<T> ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããŠããŸãã - åŒã®çµæã®å®è¡æåã¯ãåºã«ãªãåãã§ãã
Tã§ãããNullable<T>.HasValueãtrueã - åŒãã®ã€ã³ã¹ã¿ã³ã¹ã§ãªãå ŽåãåŒã®çµæã®å®è¡æã®åããåãžã®
TåãŸãã¯ref structã®å€æãååšããŸãã
宣èšãã¿ãŒã³ã§ã¯ããŠãŒã¶ãŒå®çŸ©ã®å€æãæé»çãªã¹ãã³å€æã¯èæ ®ãããŸããã
次ã®äŸã¯ãæåŸã® 2 ã€ã®æ¡ä»¶ã瀺ããŠããŸãã
int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
Console.WriteLine(a + b); // output: 30
}
åŒã®åã®ã¿ã確èªããã«ã¯ã次ã®äŸã«ç€ºãããã«ã倿°ã®ååã®ä»£ããã«ç Žæ£ _ ã䜿çšããŸãã
public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}
public static class TollCalculator
{
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
Car _ => 2.00m,
Truck _ => 7.50m,
null => throw new ArgumentNullException(nameof(vehicle)),
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
}
ãã®ãããæ¬¡ã®äŸã«ç€ºãããã«ã åãã¿ãŒã³ã䜿çšããŸãã
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
Car => 2.00m,
Truck => 7.50m,
null => throw new ArgumentNullException(nameof(vehicle)),
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
宣èšãã¿ãŒã³ãšåæ§ã«ãåŒã®çµæã null 以å€ã§ããã®å®è¡æã®åãäžèšã®æ¡ä»¶ã®ãããããæºããå Žåãåãã¿ãŒã³ã¯åŒãšäžèŽããŸãã
null 以å€ã確èªããã«ã¯ã次ã®äŸã«ç€ºãããã«ãnullã䜿çšããŸãã
if (input is not null)
{
// ...
}
詳现ã«ã€ããŠã¯ãC# èšèªä»æ§ã® 宣èšãã¿ãŒã³ ãš åãã¿ãŒã³ ã®ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
宿°ãã¿ãŒã³
宿°ãã¿ãŒã³ã¯ãå³ãªãã©ã³ãã宿°ã®å Žåã«==ã®ä»£æ¿æ§æã§ãã æ¬¡ã®äŸã«ç€ºãããã«ã 宿°ãã¿ãŒã³ ã䜿çšããŠãåŒã®çµæãæå®ãã宿°ãšçãããã©ããããã¹ãããŸãã
public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
1 => 12.0m,
2 => 20.0m,
3 => 27.0m,
4 => 32.0m,
0 => 0.0m,
_ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
宿°ãã¿ãŒã³ã§ã¯ã次ã®ãããªä»»æã®å®æ°åŒã䜿çšã§ããŸãã
- æŽæ°ãŸãã¯æµ®åå°æ°ç¹æ°å€ãªãã©ã«
- char
- æååãªãã©ã«
- ããŒã«å€
trueãŸãã¯false - åæåå€
- 宣èšããã宿°ãã£ãŒã«ããŸãã¯ããŒã«ã«ã®åå
null
åŒã¯å®æ°åã«å€æã§ããåã§ããå¿
èŠããããŸãããã ãã1 ã€ã®äŸå€ããããŸããåã Span<char> ãŸã㯠ReadOnlySpan<char> ã®åŒã¯ã宿°æååãšç
§åã§ããŸãã
次ã®äŸã«ç€ºãããã«ã宿°ãã¿ãŒã³ã䜿çšã㊠null ããã§ãã¯ããŸãã
if (input is null)
{
return;
}
ã³ã³ãã€ã©ã¯ãåŒã®==ãè©äŸ¡ãããšãã«ããŠãŒã¶ãŒ ãªãŒããŒããŒãã®ç倿Œç®åx is nullãåŒã³åºããªãããšãä¿èšŒããŸãã
次ã®äŸã§ç€ºãããã«ãåŠå®ãããnull 宿°ãã¿ãŒã³ã䜿ã£ãŠãnull ã§ã¯ãªãããšã調ã¹ãããšãã§ããŸãã
if (input is not null)
{
// ...
}
詳现ã«ã€ããŠã¯ãæ©èœææ¡ããŒãã®ã宿°ãã¿ãŒã³ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ã ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³ ã䜿çšããŠåŒã®çµæã宿°ãšæ¯èŒããŸãã
Console.WriteLine(Classify(13)); // output: Too high
Console.WriteLine(Classify(double.NaN)); // output: Unknown
Console.WriteLine(Classify(2.4)); // output: Acceptable
static string Classify(double measurement) => measurement switch
{
< -4.0 => "Too low",
> 10.0 => "Too high",
double.NaN => "Unknown",
_ => "Acceptable",
};
ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³ã§ã¯ãé¢ä¿æŒç®åã<ã>ã<=ããŸãã¯>=ã®ããããã䜿çšããŸãã ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³ã®å³åŽã®éšåã¯ã宿°åŒã§ããå¿
èŠããããŸãã 宿°åŒã«ã¯ãæŽæ°ãæµ®åå°æ°ç¹ãcharããŸãã¯åæåãæå®ã§ããŸãã
åŒã®çµæãç¹å®ã®ç¯å²å
ã«ãããã©ããããã§ãã¯ããã«ã¯ã次ã®äŸã«ç€ºãããã«ãæ¥ç¶çandãã¿ãŒã³ã«å¯ŸããŠããããäžèŽãããŸãã
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 3, 14))); // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 7, 19))); // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 2, 17))); // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
>= 3 and < 6 => "spring",
>= 6 and < 9 => "summer",
>= 9 and < 12 => "autumn",
12 or (>= 1 and < 3) => "winter",
_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
åŒã®çµæã null ãããå ŽåããŸã㯠null èš±å®¹å€æãŸãã¯ããã¯ã¹åè§£é€å€æã䜿çšããŠå®æ°ã®åã«å€æã§ããªãå Žåããªã¬ãŒã·ã§ãã« ãã¿ãŒã³ã¯åŒãšäžèŽããŸããã
詳现ã«ã€ããŠã¯ãC# èšèªä»æ§ã® ãªã¬ãŒã·ã§ãã« ãã¿ãŒã³ ã«é¢ããã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
è«çãã¿ãŒã³
notãandãããã³or ãã¿ãŒã³ã®çµã¿åããåã䜿çšããŠã次ã®è«çãã¿ãŒã³ãäœæããŸãã
åŠå®ããããã¿ãŒã³ãåŒã«äžèŽããªãå Žåã«ãåŒã«äžèŽããåŠå®
notãã¿ãŒã³ã 次ã®äŸã«ã宿°nullãã¿ãŒã³ãåŠå®ããŠãåŒã null ã§ãªããã©ããã確èªããæ¹æ³ã瀺ããŸããif (input is not null) { // ... }äž¡æ¹ã®ãã¿ãŒã³ãåŒã«äžèŽããå Žåã«ãåŒã«äžèŽããæ¥ç¶ç
andãã¿ãŒã³ã 次ã®äŸã«ããªã¬ãŒã·ã§ãã« ãã¿ãŒã³ãçµã¿åãããŠãå€ãç¹å®ã®ç¯å²å ã«ãããã©ããããã§ãã¯ããæ¹æ³ã瀺ããŸããConsole.WriteLine(Classify(13)); // output: High Console.WriteLine(Classify(-100)); // output: Too low Console.WriteLine(Classify(5.7)); // output: Acceptable static string Classify(double measurement) => measurement switch { < -40.0 => "Too low", >= -40.0 and < 0 => "Low", >= 0 and < 10.0 => "Acceptable", >= 10.0 and < 20.0 => "High", >= 20.0 => "Too high", double.NaN => "Unknown", };次ã®äŸã«ç€ºãããã«ãããããã®ãã¿ãŒã³ãåŒã«äžèŽããå Žåã«ãåŒã«äžèŽãã "颿¥ç" ãã¿ãŒã³ã
orConsole.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19))); // output: winter Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9))); // output: autumn Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11))); // output: spring static string GetCalendarSeason(DateTime date) => date.Month switch { 3 or 4 or 5 => "spring", 6 or 7 or 8 => "summer", 9 or 10 or 11 => "autumn", 12 or 1 or 2 => "winter", _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."), };
åã®äŸã«ç€ºãããã«ããã¿ãŒã³ã®çµã¿åããåããã¿ãŒã³ã§ç¹°ãè¿ã䜿çšã§ããŸãã
åªå é äœãšãã§ãã¯ã®é åº
ãã¿ãŒã³ ã³ã³ãã€ããŒã¿ãŒã¯ãåŒã®ãã€ã³ãé åºã«åºã¥ããŠãåŒã次ã®é åºã§ãã§ãã¯ããŸãã
notandor
not ãã¿ãŒã³ã¯ãæåã«ãã®ãªãã©ã³ãã«ãã€ã³ããããŸãã
and ãã¿ãŒã³ã¯ãä»»æã®notãã¿ãŒã³åŒãã€ã³ãã®åŸã«ãã€ã³ããããŸãã
or ãã¿ãŒã³ã¯ããã¹ãŠã®notãã¿ãŒã³ãšand ãã¿ãŒã³ããªãã©ã³ãã«ãã€ã³ããããåŸã«ãã€ã³ããããŸãã æ¬¡ã®äŸã§ã¯ãå°æåã§ã¯ãªããaã䜿çšããŠzãã¹ãŠã®æåãç
§åããããšããŸãã
not ãã¿ãŒã³ã®åã«and ãã¿ãŒã³ããã€ã³ããããããããšã©ãŒãçºçããŸãã
// Incorrect pattern. `not` binds before `and`
static bool IsNotLowerCaseLetter(char c) => c is not >= 'a' and <= 'z';
æ¢å®ã®ãã€ã³ãã¯ãåã®äŸã次ã®äŸã®ããã«è§£æãããŠããããšãæå³ããŸãã
// The default binding without parentheses is shows in this method. `not` binds before `and`
static bool IsNotLowerCaseLetterDefaultBinding(char c) => c is ((not >= 'a') and <= 'z');
ãšã©ãŒãä¿®æ£ããã«ã¯ã not ãã¿ãŒã³ã >= 'a' and <= 'z' åŒã«ãã€ã³ãããããã«æå®ããŸãã
// Correct pattern. Force `and` before `not`
static bool IsNotLowerCaseLetterParentheses(char c) => c is not (>= 'a' and <= 'z');
ãã¿ãŒã³ãè€éã«ãªãã«ã€ããŠããã£ãã®è¿œå ãããéèŠã«ãªããŸãã äžè¬ã«ã次ã®äŸã«ç€ºãããã«ããã£ãã䜿çšããŠä»ã®éçºè ã®ãã¿ãŒã³ãæç¢ºã«ããŸãã
static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
泚
åããã€ã³ãã£ã³ã°é åºãæã€ãã¿ãŒã³ãã³ã³ãã€ã©ããã§ãã¯ããé åºã¯æªå®çŸ©ã§ãã å®è¡æã«ãã³ã³ãã€ã©ã¯ãè€æ°ã® or ãã¿ãŒã³ãšè€æ°ã® and ãã¿ãŒã³ã®å³åŽã®å
¥ãåã«ãªã£ããã¿ãŒã³ãæåã«ç¢ºèªã§ããŸãã
詳现ã«ã€ããŠã¯ãC# èšèªä»æ§ã® ããã¿ãŒã³ ã³ã³ãã€ããŒã¿ ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãããã㣠ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ã ãããã㣠ãã¿ãŒã³ ã䜿çšããŠãå ¥ãåã«ãªã£ããã¿ãŒã³ã«å¯ŸããŠåŒã®ããããã£ãŸãã¯ãã£ãŒã«ããç §åããŸãã
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
ãããã㣠ãã¿ãŒã³ã¯ãåŒã®çµæã null 以å€ã§ãå ¥ãåã«ãªã£ããã¿ãŒã³ãåŒã®çµæã®å¯Ÿå¿ããããããã£ãŸãã¯ãã£ãŒã«ããšäžèŽããå Žåã«ãåŒãšäžèŽããŸãã
次ã®äŸã«ç€ºãããã«ãå®è¡æã®åãã§ãã¯ãšå€æ°å®£èšããããã㣠ãã¿ãŒã³ã«è¿œå ã§ããŸãã
Console.WriteLine(TakeFive("Hello, world!")); // output: Hello
Console.WriteLine(TakeFive("Hi!")); // output: Hi!
Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' })); // output: 12345
Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' })); // output: abc
static string TakeFive(object input) => input switch
{
string { Length: >= 5 } s => s.Substring(0, 5),
string s => s,
ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
ICollection<char> symbols => new string(symbols.ToArray()),
null => throw new ArgumentNullException(nameof(input)),
_ => throw new ArgumentException("Not supported input type."),
};
ãã®ã³ã³ã¹ãã©ã¯ãã¯ãå
·äœçã«ã¯ ã空 ã®ãããã㣠ãã¿ãŒã³ is { } ã null 以å€ã®ãã¹ãŠã®ãã®ã«äžèŽããããšãæå³ãã is not null ã§ã¯ãªãããã䜿çšããŠå€æ° somethingPossiblyNull is { } somethingDefinitelyNotNull ãäœæã§ããŸãã
if (GetSomeNullableStringValue() is { } nonNullValue) // Empty property pattern with variable creation
{
Console.WriteLine("NotNull:" + nonNullValue);
}
else
{
nonNullValue = "NullFallback"; // we can access the variable here.
Console.WriteLine("it was null, here's the fallback: " + nonNullValue);
}
ãããã㣠ãã¿ãŒã³ã¯ãååž°çãã¿ãŒã³ã§ãã å ¥ãåã«ãªã£ããã¿ãŒã³ãšããŠä»»æã®ãã¿ãŒã³ã䜿çšã§ããŸãã æ¬¡ã®äŸã«ç€ºãããã«ãå ¥ãåã«ãªã£ããã¿ãŒã³ã«å¯ŸããŠãããŒã¿ã®äžéšãäžèŽãããã«ã¯ããããã㣠ãã¿ãŒã³ã䜿çšããŸãã
public record Point(int X, int Y);
public record Segment(Point Start, Point End);
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start: { Y: 0 } } or { End: { Y: 0 } };
åã®äŸã§ã¯ãorãã¿ãŒã³é£çµåãšã¬ã³ãŒãåã䜿çšããŠããŸãã
å ¥ãåã«ãªã£ãããããã£ãŸãã¯ãã£ãŒã«ãã¯ããããã㣠ãã¿ãŒã³å ã§åç §ã§ããŸãã ãã®æ©èœã¯ "æ¡åŒµãããã㣠ãã¿ãŒã³" ãšåŒã°ããŸãã ããšãã°ãåã®äŸã®ã¡ãœãããæ¬¡ã®åçã®ã³ãŒãã«ãªãã¡ã¯ã¿ãªã³ã°ã§ããŸãã
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };
詳现ã«ã€ããŠã¯ãC# æšæºã® ãããã㣠ãã¿ãŒã³ ã«é¢ããã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãã³ã
ã³ãŒãã®èªã¿ããããåäžãããã«ã¯ã ãããã㣠ãã¿ãŒã³ã®ç°¡ç¥å (IDE0170) ã¹ã¿ã€ã« ã«ãŒã«ã䜿çšããŸãã æ¡åŒµãããã㣠ãã¿ãŒã³ã䜿çšããå Žæãææ¡ããŸãã
äœçœ®æå®ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ã äœçœ®æå®ãã¿ãŒã³ ã䜿çšããŠåŒãåè§£ããçµæã®å€ã察å¿ããå ¥ãåã«ãªã£ããã¿ãŒã³ãšç §åããŸãã
public readonly struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
(0, 0) => "Origin",
(1, 0) => "positive X basis end",
(0, 1) => "positive Y basis end",
_ => "Just a point",
};
åã®äŸã§ã¯ãåŒã®åã« Deconstruct ã¡ãœãããå«ãŸããŠããŸãããã®ã¡ãœããã¯ããã¿ãŒã³ãåŒã®çµæãåè§£ããããã«äœ¿çšããŸãã
éèŠ
äœçœ®æå®ãã¿ãŒã³ã®ã¡ã³ããŒã®é åºã¯ãDeconstruct ã¡ãœããã®ãã©ã¡ãŒã¿ãŒã®é åºãšäžèŽããå¿
èŠããããŸãã äœçœ®æå®ãã¿ãŒã³çšã«çæãããã³ãŒãã¯ã Deconstruct ã¡ãœãããåŒã³åºããŸãã
ãŸããäœçœ®æå®ãã¿ãŒã³ã«å¯ŸããŠã¿ãã«åã®åŒãäžèŽãããããšãã§ããŸãã ãã®æ¹æ³ã䜿çšãããšã次ã®äŸã«ç€ºãããã«ãè€æ°ã®å ¥åãããŸããŸãªãã¿ãŒã³ãšç §åã§ããŸãã
static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate)
=> (groupSize, visitDate.DayOfWeek) switch
{
(<= 0, _) => throw new ArgumentException("Group size must be positive."),
(_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m,
(>= 5 and < 10, DayOfWeek.Monday) => 20.0m,
(>= 10, DayOfWeek.Monday) => 30.0m,
(>= 5 and < 10, _) => 12.0m,
(>= 10, _) => 15.0m,
_ => 0.0m,
};
åã®äŸã§ã¯ããªã¬ãŒã·ã§ãã« ãã¿ãŒã³ãšè«çãã¿ãŒã³ã䜿çšããŠããŸãã
次ã®äŸã«ç€ºãããã«ãäœçœ®æå®ãã¿ãŒã³ã§ã¿ãã«èŠçŽ ãš Deconstruct ãã©ã¡ãŒã¿ãŒã®ååã䜿çšã§ããŸãã
var numbers = new List<int> { 1, 2, 3 };
if (SumAndCount(numbers) is (Sum: var sum, Count: > 0))
{
Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}"); // output: Sum of [1 2 3] is 6
}
static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers)
{
int sum = 0;
int count = 0;
foreach (int number in numbers)
{
sum += number;
count++;
}
return (sum, count);
}
ãŸããæ¬¡ã®ããããã®æ¹æ³ã§äœçœ®æå®ãã¿ãŒã³ãæ¡åŒµããããšãã§ããŸãã
次ã®äŸã«ç€ºãããã«ãã©ã³ã¿ã€ã åãã§ãã¯ãšå€æ°å®£èšã远å ããŸãã
public record Point2D(int X, int Y); public record Point3D(int X, int Y, int Z); static string PrintIfAllCoordinatesArePositive(object point) => point switch { Point2D (> 0, > 0) p => p.ToString(), Point3D (> 0, > 0, > 0) p => p.ToString(), _ => string.Empty, };åã®äŸã§ã¯ã ã¡ãœãããæé»çã«æäŸãã
Deconstructã䜿çšããŠããŸããæ¬¡ã®äŸã«ç€ºãããã«ãäœçœ®æå®ãã¿ãŒã³å ã§ãããã㣠ãã¿ãŒã³ã䜿çšããŸãã
public record WeightedPoint(int X, int Y) { public double Weight { get; set; } } static bool IsInDomain(WeightedPoint point) => point is (>= 0, >= 0) { Weight: >= 0.0 };次ã®äŸã«ç€ºãããã«ãäžèšã® 2 ã€ã®äœ¿çšæ³ãçµã¿åãããŸãã
if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p) { // .. }
äœçœ®æå®ãã¿ãŒã³ã¯ãååž°çãã¿ãŒã³ã§ãã ã€ãŸããå ¥ãåã«ãªã£ããã¿ãŒã³ãšããŠä»»æã®ãã¿ãŒã³ã䜿çšã§ããŸãã
詳现ã«ã€ããŠã¯ãæ©èœææ¡ããŒãã®ãäœçœ®æå®ãã¿ãŒã³ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
var ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ã var ãã¿ãŒã³ ã䜿çšããŠã nullãå«ãä»»æã®åŒãç
§åãããã®çµæãæ°ããããŒã«ã«å€æ°ã«å²ãåœãŠãŸãã
static bool IsAcceptable(int id, int absLimit) =>
SimulateDataFetch(id) is var results
&& results.Min() >= -absLimit
&& results.Max() <= absLimit;
static int[] SimulateDataFetch(int id)
{
var rand = new Random();
return Enumerable
.Range(start: 0, count: 5)
.Select(s => rand.Next(minValue: -10, maxValue: 11))
.ToArray();
}
var ãã¿ãŒã³ã¯ãäžéèšç®ã®çµæãä¿æããããã«ããŒã«åŒå
ã«äžæå€æ°ãå¿
èŠãªå Žåã«äŸ¿å©ã§ãã ããã«ã次ã®äŸã«ç€ºãããã«ãvar åŒãŸãã¯ã¹ããŒãã¡ã³ãã® when case guard ã§è¿œå ã®ãã§ãã¯ãå®è¡ããå¿
èŠãããå Žåã¯ãswitch ãã¿ãŒã³ã䜿çšããããšãã§ããŸãã
public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
var (x, y) when x < y => new Point(-x, y),
var (x, y) when x > y => new Point(x, -y),
var (x, y) => new Point(x, y),
};
static void TestTransform()
{
Console.WriteLine(Transform(new Point(1, 2))); // output: Point { X = -1, Y = 2 }
Console.WriteLine(Transform(new Point(5, 2))); // output: Point { X = 5, Y = -2 }
}
åã®äŸã§ããã¿ãŒã³ var (x, y) 㯠äœçœ®æå®ãã¿ãŒã³(var x, var y) ãšåãã§ãã
var ãã¿ãŒã³ã§ã¯ã宣èšããã倿°ã®åã¯ããã¿ãŒã³ãäžèŽããåŒã®ã³ã³ãã€ã«æã®åã§ãã
詳现ã«ã€ããŠã¯ãæ©èœææ¡ããŒãã®ãVar ãã¿ãŒã³ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ç Žæ£ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ç Žæ£_ã䜿çšããŠãnullãå«ãä»»æã®åŒãšäžèŽãããŸãã
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday)); // output: 5.0
Console.WriteLine(GetDiscountInPercent(null)); // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10)); // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
DayOfWeek.Monday => 0.5m,
DayOfWeek.Tuesday => 12.5m,
DayOfWeek.Wednesday => 7.5m,
DayOfWeek.Thursday => 12.5m,
DayOfWeek.Friday => 5.0m,
DayOfWeek.Saturday => 2.5m,
DayOfWeek.Sunday => 2.0m,
_ => 0.0m,
};
åã®äŸã§ã¯ãç Žæ£ãã¿ãŒã³ã¯ null ãšã DayOfWeek åæäœã®å¯Ÿå¿ããã¡ã³ããŒãæããªãæŽæ°å€ãåŠçããŸãã ãã®ä¿èšŒã«ããããã®äŸã® switch åŒã§ã䜿çšå¯èœãªãã¹ãŠã®å
¥åå€ã確å®ã«åŠçãããŸãã
switch åŒã§ç Žæ£ãã¿ãŒã³ã䜿çšãããåŒã®ãã¿ãŒã³ãå
¥åã«äžèŽããªãå Žåãã©ã³ã¿ã€ã ã«ãã£ãŠãäŸå€ãã¹ããŒãããŸãã
switch åŒã§ãã¹ãŠã®å¯èœãªå
¥åå€ãåŠçãããªãå Žåãã³ã³ãã€ã©ã§èŠåãçæãããŸãã
ç Žæ£ãã¿ãŒã³ããis åŒãŸã㯠switch ã¹ããŒãã¡ã³ãã§ãã¿ãŒã³ã«ããããšã¯ã§ããŸããã ãã®ãããªå Žåãä»»æã®åŒã«äžèŽãããã«ã¯ãç Žæ£ãå«ã var ãã¿ãŒã³var _ ã䜿çšããŸãã ç Žæ£ãã¿ãŒã³ããswitch åŒã§ãã¿ãŒã³ã«ããããšã¯ã§ããŸããã
詳现ã«ã€ããŠã¯ãæ©èœææ¡ããŒãã®ãç Žæ£ãã¿ãŒã³ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãã£ãã§å²ãŸãããã¿ãŒã³
ä»»æã®ãã¿ãŒã³ããã£ãã§å²ãããšãã§ããŸãã éåžžã¯ã次ã®äŸã«ç€ºãããã«ããã£ãã䜿çšã㊠è«çãã¿ãŒã³ã®åªå é äœã匷調ãŸãã¯å€æŽããŸãã
if (input is not (float or double))
{
return;
}
ãªã¹ã ãã¿ãŒã³
次ã®äŸã«ç€ºãããã«ãé åãŸãã¯ãªã¹ããäž é£ ã®ãã¿ãŒã³ãšç §åã§ããŸãã
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
Console.WriteLine(numbers is [1, 2, 3, 4]); // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // True
åã®äŸã«ç€ºãããã«ãå ¥ãåã«ãªã£ãåãã¿ãŒã³ãå ¥åã·ãŒã±ã³ã¹ã®å¯Ÿå¿ããèŠçŽ ãšäžèŽãããšããªã¹ã ãã¿ãŒã³ãäžèŽããŸãã ãªã¹ã ãã¿ãŒã³å ã§ã¯ä»»æã®ãã¿ãŒã³ã䜿çšã§ããŸãã ä»»æã®èŠçŽ ãšäžèŽããã«ã¯ã ç Žæ£ãã¿ãŒã³ ã䜿çšããããèŠçŽ ããã£ããã£ããå Žåã¯ã次ã®äŸã«ç€ºãããã« var ãã¿ãŒã³ã䜿çšããŸãã
List<int> numbers = new() { 1, 2, 3 };
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.
äžèšã®äŸã§ã¯ãå
¥åã·ãŒã±ã³ã¹å
šäœããªã¹ã ãã¿ãŒã³ãšç
§åããŠããŸãã æ¬¡ã®äŸã«ç€ºãããã«ãå
¥åã·ãŒã±ã³ã¹ã®å
é ãŸãã¯æ«å°Ÿ (ãŸãã¯ãã®äž¡æ¹) ã§ã®ã¿èŠçŽ ãç
§åããã«ã¯ã ã¹ã©ã€ã¹ ãã¿ãŒã³..ã䜿çšããŸãã
Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]); // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]); // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]); // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]); // False
Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]); // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]); // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]); // True
Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]); // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]); // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]); // False
ã¹ã©ã€ã¹ ãã¿ãŒã³ã§ã¯ 0 å以äžã®èŠçŽ ãç §åããŸãã ãªã¹ã ãã¿ãŒã³ã§ã¯æå€§ 1 ã€ã®ã¹ã©ã€ã¹ ãã¿ãŒã³ã䜿çšã§ããŸãã ã¹ã©ã€ã¹ ãã¿ãŒã³ã¯ããªã¹ã ãã¿ãŒã³ã§ã®ã¿è¡šç€ºã§ããŸãã
次ã®äŸã«ç€ºãããã«ãã¹ã©ã€ã¹ ãã¿ãŒã³å ã§ãµããã¿ãŒã³ãå ¥ãåã«ããããšãã§ããŸãã
void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.
void Validate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}
Validate(new[] { -1, 0, 1 }); // output: not valid
Validate(new[] { -1, 0, 0, 1 }); // output: valid
詳现ã«ã€ããŠã¯ãC# èšèªä»æ§ã® ãªã¹ã ãã¿ãŒã³ ãåç §ããŠãã ããã
C# 15 以éã§ã¯ãæ¡åŒµæ©èœã®ã€ã³ããã¯ã¹äœæã¡ã³ããŒã¯ããªã¹ã ãã¿ãŒã³ã§å¿ èŠãªã«ãŠã³ããšèŠçŽ ã®ã¢ã¯ã»ã¹ãæäŸã§ããŸãã äŸã«ã€ããŠã¯ãã æ¡åŒµã€ã³ãã¯ãµãŒããåç §ããŠãã ããã
éããéå±€ãã¿ãŒã³
C# 15 以éã§ã¯ãå¶åŸ¡åã switch ã¯ã©ã¹ã§ããclosedåŒã¯ããã®ã¯ã©ã¹ã®ãã¹ãŠã®çŽæ¥åå«ãã¢ãŒã ãåŠçããéã«ç¶²çŸ
çã§ãã ã¹ã€ããã¯å®å
šã§ãããããã³ã³ãã€ã©ã¯æ¢å®ã®ã¢ãŒã ãå¿
èŠãšããŸããã
public closed record class PaymentMethod;
public record class Cash : PaymentMethod;
public record class Card(string Last4) : PaymentMethod;
public record class BankTransfer(string Iban) : PaymentMethod;
public static string Describe(PaymentMethod method) => method switch
{
Cash => "cash",
Card(var last4) => $"card ending {last4}",
BankTransfer(var iban) => $"bank transfer to {iban}",
// No warning: every direct descendant of 'PaymentMethod' is handled.
};
éããéå±€ã¹ã€ããã¯ããã¹ãŠã®çŽæ¥åå«ãã¹ã€ããã®å Žæããå°éå¯èœãªå Žåã«ã®ã¿ç¶²çŸ çã§ãã çŽæ¥ã®åå«ãéããåºæ¬åãããã¢ã¯ã»ã¹ãããããªããã¹ã€ãã ãµã€ãã«è¡šç€ºãããªãå Žåãã³ã³ãã€ã©ã¯ãããæªåŠçãšããŠæ±ããã¹ã€ãããç¶²çŸ çã§ã¯ãªãããšãèŠåããŸãã
ããšãã°ãéãã public åºåºã¯ã©ã¹ã«ã¯ã internal çŽæ¥åå«ãå«ããããšãã§ããŸãã åãã¢ã»ã³ããªå
ã®ã³ãŒãã«ã¯åå«ã®å®å
šãªã»ããã衚瀺ãããŸãããå¥ã®ã¢ã»ã³ããªå
ã®ã³ãŒãã§ã¯æ¬¡ã®åŠçã¯è¡ãããŸããã
// Assembly 1
public closed record class Shape;
public record class Circle(double Radius) : Shape;
internal record class Triangle(double Base, double Height) : Shape;
// Same assembly: 'Triangle' is visible, so the switch is exhaustive.
internal static double Area(Shape shape) => shape switch
{
Circle(var r) => Math.PI * r * r,
Triangle(var b, var h) => 0.5 * b * h,
};
// Assembly 2
public static string Name(Shape shape) => shape switch
{
Circle => "circle",
// Warning CS8509: the switch expression doesn't handle all possible values.
// 'Triangle' is a direct descendant of 'Shape' but isn't visible here.
};
ã¢ã»ã³ã㪠2 ã®å®å
šãã埩å
ããã«ã¯ãç Žæ£ã¢ãŒã (_ => ...) ã远å ããããåºåºã¯ã©ã¹ã® arm (åã®äŸã§Shape ) ã远å ãããããŸãã¯ãã¹ãŠã®çŽæ¥åå«ãå°ãªããšãéããåºæ¬åãšããŠã¢ã¯ã»ã¹ã§ããããã«ããŸãã
å¶åŸ¡åã null 蚱容ã®å Žåã null ã¯ã¹ã€ãããåŠçããå¿
èŠããã远å ã®å€ã§ãã
PaymentMethod?ã¢ãŒã ãçç¥ããnullã®åãæ¿ãã¯ããã¹ãŠã®çŽæ¥åå«ãäžèŽããå Žåã§ãç¶²çŸ
çã§ã¯ãããŸããã
éããã¯ã©ã¹ããã®æŽŸçã¯æšç§»çã§ã¯ãããŸãããéããã¯ã©ã¹ã®ééããåå«ã¯ãä»ã®ã¢ã»ã³ããªããæŽŸçã§ããŸãã ã³ã³ãã€ã©ã¯ ãçŽæ¥ ã®åå«ã®ã¿ãå®å
šãªã»ãããšããŠæ±ããŸãã åå«ãåãæ¿ããå Žåããç¶²çŸ
æ§ãã§ãã¯ã®æ©æµãåããããã«ãåå« closed (ãŸã㯠sealed) ã宣èšããŸãã
鿥åå«ã¯éããããŒã¹ã®å®å
šãªã»ãããæ¡åŒµããªããããå®å
šæ§ãæºããããã«ãã¹ãŠã®æšç§»çãµãã¿ã€ãã«ã¢ãŒã ã远å ããå¿
èŠã¯ãããŸããã ã¢ãŒã éã®åéã¯ãã©ã®ã¯ã©ã¹éå±€ã§ãåæ§ã«æ©èœããŸããåºæ¬åãšäžèŽããã¢ãŒã ã¯ãã¹ãŠã®ãµãã¿ã€ããã«ããŒãããããã®ãµãã¿ã€ãã®ããããã«äžèŽããåŸã®ã¢ãŒã ã«ã¯å°éã§ããŸããã çŽæ¥ã®åå«ãVehicleããã³Carã§ããéããTruckã«å ããŠãå¥ã®ã¢ã»ã³ããªã§å®£èšããã鿥çãªåå«SedanèããŠã¿ãŸãããã
// Assembly 1
public closed record class Vehicle;
public record class Car(int Doors) : Vehicle;
public record class Truck(double PayloadTons) : Vehicle;
// Assembly 2
public record class Sedan(int Doors) : Car(Doors);
Vehicleã®åãæ¿ãã¯ãCarãååšããå Žåã§ããTruckãšSedanãåŠçããåŸã«å®å
šã«å®è¡ãããŸãã
Carã¢ãŒã ã¯ããã¹ãŠã®Sedanå€ãã«ããŒããŸãã
public static string Category(Vehicle v) => v switch
{
Car => "car",
Truck => "truck",
// No warning. The 'Car' arm covers 'Sedan' through ordinary subtype matching.
};
ç¹ã«Sedanã«ãã£ã¹ãããããã«ã¯ãã¢ãŒã ã®Carè
ã眮ãå¿
èŠããããŸãã
Carã¢ãŒã ã¯ãCarã§ã¯ãªããã¹ãŠã®SedanãšåŒãç¶ãäžèŽãããããå°éå¯èœãªãŸãŸã«ãªããŸãã
public static string CategorySedanFirst(Vehicle v) => v switch
{
Sedan => "sedan",
Car => "car", // Reachable: 'Car' values that aren't 'Sedan'.
Truck => "truck",
};
ããã 2 ã€ã®ã¢ãŒã ãå転ãããšãä»ã®ã¯ã©ã¹éå±€ã®å Žåãšåæ§ã«ãåéãšã©ãŒãçºçããŸãã ã³ã³ãã€ã©ã¯ã Car arm ãæ¢ã« Sedanãã«ããŒããŠããããšãæ€åºããŸãã
string Category(Vehicle v) => v switch
{
Car => "car",
Sedan => "sedan", // Error CS8510: the pattern is unreachable. It has already been handled by 'Car => ...'.
Truck => "truck",
};
éå±€ãããã«å®å
šã«ãã©ããŒããå Žåã¯ã Car èªäœã closed宣èšããŸãã ã³ã³ãã€ã©ã¯ã Car ã®ãã¹ãŠã®çŽæ¥åå« ( Sedan ãªã©) ãã Carã«æ ¹ãããå®å
šãªã»ãããšããŠæ±ããŸãã 管çã®çš®é¡ã Car ã¹ã€ããã¯ã次ã®ããããã®å Žåã«ç¶²çŸ
çã§ãã
-
Carã®ãã¹ãŠã®çŽæ¥åå«ãç¬èªã®è ã§åŠçããŸãã - ãã¹ãŠã®
Carå€ (ãã¹ãŠã®ãµãã¿ã€ããå«ã) ãã«ããŒããCararm ãå«ãŸããŸãã - ç Žæ£ã¢ãŒã (
_ => ...) ãŸãã¯åºæ¬ã¿ã€ãã®Carçšã®ã¢ãŒã (Vehicleãªã©) ãå«ãŸããŸãã
管çã®çš®é¡ãVehicleã¹ã€ããã«ã¯éžæè¢ããããŸããCarãšTruckãåŠçããã³ãŒãã¯ãCarã®ãã¹ãŠã®ãµãã¿ã€ããCar arm ãã«ããŒãããããäŸç¶ãšããŠç¶²çŸ
çã§ãã
Car
closedããŒã¯ãããšããã®ã¹ã€ããã® 2 ã€ç®ã®ãªãã·ã§ã³ã衚瀺ãããŸãã åäžã® Car ã¢ãŒã ãä¿æãããã Car ã®çŽæ¥ã®åå«( Truck ã¢ãŒã ãšå
±ã«)ããšã«1ã€ã®ã¢ãŒã ã«çœ®ãæããŠãããã§ãå®å
šã«ããããšãã§ããŸãã
ãŸãã Carclosed ããŒã¯ãããšæé»çã« abstractãããããã Car ã®ã€ã³ã¹ã¿ã³ã¹ãçŽæ¥äœæã§ããªããªããŸãã ãã®æ¡ä»¶ãèšèšã«é©åããªãå¯èœæ§ããããŸãã
Carã峿ã«ç¶æããå¿
èŠãããå Žåã¯ãéãããŸãŸã«ããŠãåã«ç€ºããããã«è
ãæ³šæããããšã§ãæ°ã«ãªãç¹å®ã®ãµãã¿ã€ãã«ãã£ã¹ãããããŸãã
åãã©ã¡ãŒã¿ãŒã®ç®¡çå
éããéå±€æ©èœä»æ§ã§ã¯ãå¶åŸ¡åãéããã¯ã©ã¹ã«å¶çŽãããåãã©ã¡ãŒã¿ãŒã§ããswitchåŒããéããã¯ã©ã¹èªäœã®åãæ¿ããšåãçšèªã«å®å
šã«å®çŸ©ããŸãã ãã®ããããžã§ããªã㯠ã³ãŒãã¯ãåãã©ã¡ãŒã¿ãŒãéããåºåºã«å¶çŽãããã¹ãŠã®çŽæ¥åå«ãåŠçããããšã§ãéããéå±€ã«ãã£ã¹ãããã§ããŸãã
public static string Describe<X>(X method) where X : PaymentMethod => method switch
{
Cash => "cash",
Card(var last4) => $"card ending {last4}",
BankTransfer(var iban) => $"bank transfer to {iban}",
// No warning: 'X' is constrained to the closed type 'PaymentMethod', so the
// compiler treats this switch as exhaustive because every direct descendant is handled.
};
詳现ã«ã€ããŠã¯ã éãã修食åãåç §ããŠãã ããã 仿§ã«ã€ããŠã¯ãã éããéå±€ããåç §ããŠãã ããã
å ±çšäœãã¿ãŒã³
C# 15 ã§ã¯ã å
±çšäœåãå°å
¥ãããŠããŸãã å
±çšäœåŒã«åãŸãã¯å®£èšãã¿ãŒã³ãé©çšãããšããã¿ãŒã³ã¯å
±çšäœã€ã³ã¹ã¿ã³ã¹ã§ã¯ãªãå
±çšäœã®å
容ããã¹ãããŸãã ããšãã°ããããã®ã±ãŒã¹ã®åã¯ãããã Name ããããã£ãæã¡ã Dog ã«ã¯ Breed ããããã£ããããŸãã
public record class Cat(string Name);
public record class Dog(string Name, string Breed);
次㮠Pet å
±çšäœã¯ãç¬èªã®èªã¿åãå°çšã® Name ããããã£ãå
¬éããŸãããã®ããããã£ã¯ãå
å«ã±ãŒã¹ã«ããªã²ãŒãããŸãã
public union Pet(Cat, Dog)
{
public string Name => this switch
{
Cat cat => cat.Name,
Dog dog => dog.Name,
null => "",
};
}
åæå®ãããååž°ãã¿ãŒã³ã§ã¯ãå
容ããã¹ããããŸããå«ãŸããŠããç¬ã®Breedãèªã¿åDog { Breed: "Labrador" }ãå
±çšäœã«å«ãŸããŠããªãããããã£ãèªã¿åãããŸãã ããã«å¯Ÿããåæå®ãããŠããªãããããã£ãšäœçœ®æå®ãã¿ãŒã³ãšãªã¹ã ãã¿ãŒã³ã§ã¯ãå
±çšäœã€ã³ã¹ã¿ã³ã¹ã®ã¡ã³ããŒã䜿çšãããŸãã ããã§ã¯ã { Name: "Rex" } ã¯å
±çšäœã® Name ããããã£ãèªã¿åãã®ã§ããã®ååã®ç«ãŸãã¯ç¬ã®ãããããšäžèŽããŸãã
Pet pet = new Dog("Rex", "Labrador");
Console.WriteLine(pet is Dog { Breed: "Labrador" }); // output: True
Console.WriteLine(pet is { Name: "Rex" }); // output: True
pet = new Cat("Rex");
Console.WriteLine(pet is Dog { Breed: "Labrador" }); // output: False
Console.WriteLine(pet is { Name: "Rex" }); // output: True
ãããã®èŠåã¯ã is åŒãš switch åŒã®äž¡æ¹ã«é©çšãããŸãã ç Žæ£ _ ãã¿ãŒã³ã¯åä¿¡å
±çšäœãšäžèŽãã var ãã¿ãŒã³ã¯ã©ããè§£é€ããã«ããããã£ããã£ããŸãã
null ãã¿ãŒã³ã¯ãå
±çšäœã®å
容ã null ã§ãããã©ããããã§ãã¯ããŸãã ãŸããã¯ã©ã¹ ããŒã¹ã®å
±çšäœåç
§ãŸã㯠null 蚱容å
±çšäœã©ãããŒã null ã®å Žåã«ãæåããŸãã
not ãã¿ãŒã³ã¯å
¥ãåã«ãªã£ããã¿ãŒã³ãåŠå®ãããããpet is not null㯠null 以å€ã®å
容ããã¹ãããŸãã 空ã®åæå®ãããŠããªããããã㣠ãã¿ãŒã³ pet is { }ã代ããã«å
±çšäœã€ã³ã¹ã¿ã³ã¹ããã¹ãããŸãããã®å
容ã null ã®å Žåã§ããnull ã«ã§ããªãæ§é äœå
±çšäœãšäžèŽããŸãã
åãã¿ãŒã³ã¯ãå°ãªããšã 1 ã€ã®ã±ãŒã¹åãšäºææ§ãããå¿
èŠããããŸãã äžèšã® Pet 宣èšã§ã¯ã pet is Pet ã¯å
±çšäœã€ã³ã¹ã¿ã³ã¹ããã¹ãããã®ã§ã¯ãªããã³ã³ãã€ã© ãšã©ãŒ CS8121 ãçæããŸãã
Petã¯ã±ãŒã¹åã§ãããããunion Pet(Cat, Dog, Pet)ãªã©ã®ååž°çãªå®£èšã«æåããå¯èœæ§ããããŸãã ååž°å
±çšäœã䜿çšãããšããããã®ãã¹ãã誀ã£ãŠè§£éãããããªããŸãããã®ãã¿ãŒã³ã¯ãå€åŽã®ã€ã³ã¹ã¿ã³ã¹ã§ã¯ãªããå«ãŸããŠãã Petããã¹ãããŸãã éå埩çãªå
±çšäœå®£èšãåªå
ããŸãã
å
±çšäœåã éããã¯ã¹åã¢ã¯ã»ã¹ ãã¿ãŒã³ãæäŸããå Žåãã³ã³ãã€ã©ã¯åãã¿ãŒã³ ãã§ãã¯çšã« TryGetValue ãåŒã³åºããnull ãã¿ãŒã³ ãã§ãã¯ã« HasValue ããå€åã®å Žåã¯ããã¯ã¹åãåé¿ããŸãã åã¡ã³ããŒã¯ãç¬èªã®ãã¿ãŒã³ã®çš®é¡ã«é©çšãããŸããã©ã¡ãããããäžæ¹ã®ãã¿ãŒã³ã®ãã©ãŒã«ããã¯ã§ããããŸããã ã¡ã³ããŒãèŠã€ãããªãå Žåãã³ã³ãã€ã©ã¯ä»£ããã«ãã®ãã¿ãŒã³ã® Value ããããã£ããã§ãã¯ããŸãã
詳现ã«ã€ããŠã¯ãã å ±çšäœã®ç §åããåç §ããŠãã ããã 仿§ã«ã€ããŠã¯ãã å ±çšäœããåç §ããŠãã ããã
C# èšèªä»æ§
詳现ã«ã€ããŠã¯ã次ã®ãã㪠C# èšèªä»æ§ã®ãã¿ãŒã³ãšãã¿ãŒã³ ãããã³ã°ã®ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã