C# 개념 (1)-네임스페이스,튜플,형식분해 네임스페이스(namespace) 1 System.Console.WriteLine("Hello World!" );
위 코드에서 System
은 네임스페이스고 Console
은 네임스페이스에 클래스입니다.
1 2 3 4 using System;Console.WriteLine("Hello World!" );
위처럼 using 키워드를 사용해서 사용할수도 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 namespace SampleNamespace { class SampleClass { public void SampleMethod () { System.Console.WriteLine( "SampleMethod inside SampleNamespace" ); } } }
고유한 네임스페이스를 선언하면 대규모 프로그래밍 프로젝트에서 클래스 및 메서드 이름에 범위를 지정할수 있습니다.
튜플(tuples) 및 형식분해(Deconstructing) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 using System;public class Example { public static void Main () { var result = QueryCityData("New York City" ); var city = result.Item1; var pop = result.Item2; var size = result.Item3; } private static (string , int , double ) QueryCityData (string name ) { if (name == "New York City" ) return (name, 8175133 , 468.48 ); return ("" , 0 , 0 ); } }
위처럼 QueryCityData
메서드는 3 튜플을 반환하며 별도에 작업을 해야 변수에 할당됩니다.
튜플 분해 1 2 3 4 5 6 7 public static void Main (){ (string city, int population, double area) = QueryCityData("New York City" ); }
위처럼 직접적으로 변수 타입을 지정할수도 있고
1 2 3 4 5 6 7 public static void Main (){ var (city, population, area) = QueryCityData("New York City" ); }
타입을 유추할수 있게 처리 할수도 있게 할수도 있고
1 2 3 4 5 6 7 public static void Main (){ (string city, var population, var area) = QueryCityData("New York City" ); }
개별적으로 var 키워드를 쓸수도 있다.
마지막으로는 기존에 있는 변수를 활용할수도 있다.
1 2 3 4 5 6 7 8 9 10 11 public static void Main (){ string city = "Raleigh" ; int population = 458880 ; double area = 144.8 ; (city, population, area) = QueryCityData("New York City" ); }
무시 항목을 사용한 튜플 분해 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 using System;using System.Collections.Generic;public class Example { public static void Main () { var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City" , 1960 , 2010 ); Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0} " ); } private static (string , double , int , int , int , int ) QueryCityDataForYears (string name, int year1, int year2 ) { int population1 = 0 , population2 = 0 ; double area = 0 ; if (name == "New York City" ) { area = 468.48 ; if (year1 == 1960 ) { population1 = 7781984 ; } if (year2 == 2010 ) { population2 = 8175133 ; } return (name, area, year1, population1, year2, population2); } return ("" , 0 , 0 , 0 , 0 , 0 ); } }
사용자 정의 형식 분해 c#은 튜플이 아닌 형식의 분해는 기본적으로 제공하지 않습니다. 그러나 클래스, 구조체 또는 인터페이스를 만든 이는 하나이상의 Deconstruct
메소드를 구현하여 분해할수 있습니다. out
시그니처를 활용
1 2 public void Deconstruct (out string fname, out string mname, out string lname )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 using System;public class Person { public string FirstName { get ; set ; } public string MiddleName { get ; set ; } public string LastName { get ; set ; } public string City { get ; set ; } public string State { get ; set ; } public Person (string fname, string mname, string lname, string cityName, string stateName ) { FirstName = fname; MiddleName = mname; LastName = lname; City = cityName; State = stateName; } public void Deconstruct (out string fname, out string lname ) { fname = FirstName; lname = LastName; } public void Deconstruct (out string fname, out string mname, out string lname ) { fname = FirstName; mname = MiddleName; lname = LastName; } public void Deconstruct (out string fname, out string lname, out string city, out string state ) { fname = FirstName; lname = LastName; city = City; state = State; } } public class Example { public static void Main () { var p = new Person("John" , "Quincy" , "Adams" , "Boston" , "MA" ); var (fName, lName, city, state) = p; Console.WriteLine($"Hello {fName} {lName} of {city} , {state} !" ); } }
위에 예제에서는 다양하게 Deconstruct를 구현하여 분해를 할수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 using System;public class Person { public string FirstName { get ; set ; } public string MiddleName { get ; set ; } public string LastName { get ; set ; } public string City { get ; set ; } public string State { get ; set ; } public DateTime DateOfBirth { get ; set ; } public Decimal AnnualIncome { get ; set ; } public void Deconstruct (out string fname, out string mname, out string lname, out int age ) { fname = FirstName; mname = MiddleName; lname = LastName; var today = DateTime.Today; age = today.Year - DateOfBirth.Year; if (DateOfBirth.Date > today.AddYears(-age)) age--; } public void Deconstruct (out string lname, out string fname, out string mname, out decimal income ) { fname = FirstName; mname = MiddleName; lname = LastName; income = AnnualIncome; } }
위에 코드는 변수의 순서가 틀려서 혼동이 올수 있는 케이스입니다. 이렇게 활용하면 안되겠습니다.
무시항목을 사용한 사용자 정의 형식분해 1 2 3 4 5 6 7 var (fName, _, city, _) = p;Console.WriteLine($"Hello {fName} of {city} !" );
확장 메서드를 사용한 사용자 정의 형식분해 System.Reflection.PropertyInfo
클래스에서 정의한 확장 메서드 구현이다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 using System;using System.Collections.Generic;using System.Reflection;public static class ReflectionExtensions { public static void Deconstruct (this PropertyInfo p, out bool isStatic, out bool isReadOnly, out bool isIndexed, out Type propertyType ) { var getter = p.GetMethod; isReadOnly = ! p.CanWrite; isStatic = getter.IsStatic; isIndexed = p.GetIndexParameters().Length > 0 ; propertyType = p.PropertyType; } public static void Deconstruct (this PropertyInfo p, out bool hasGetAndSet, out bool sameAccess, out string access, out string getAccess, out string setAccess ) { hasGetAndSet = sameAccess = false ; string getAccessTemp = null ; string setAccessTemp = null ; MethodInfo getter = null ; if (p.CanRead) getter = p.GetMethod; MethodInfo setter = null ; if (p.CanWrite) setter = p.SetMethod; if (setter != null && getter != null ) hasGetAndSet = true ; if (getter != null ) { if (getter.IsPublic) getAccessTemp = "public" ; else if (getter.IsPrivate) getAccessTemp = "private" ; else if (getter.IsAssembly) getAccessTemp = "internal" ; else if (getter.IsFamily) getAccessTemp = "protected" ; else if (getter.IsFamilyOrAssembly) getAccessTemp = "protected internal" ; } if (setter != null ) { if (setter.IsPublic) setAccessTemp = "public" ; else if (setter.IsPrivate) setAccessTemp = "private" ; else if (setter.IsAssembly) setAccessTemp = "internal" ; else if (setter.IsFamily) setAccessTemp = "protected" ; else if (setter.IsFamilyOrAssembly) setAccessTemp = "protected internal" ; } if (setAccessTemp == getAccessTemp) { sameAccess = true ; access = getAccessTemp; getAccess = setAccess = String.Empty; } else { access = null ; getAccess = getAccessTemp; setAccess = setAccessTemp; } } } public class Example { public static void Main () { Type dateType = typeof (DateTime); PropertyInfo prop = dateType.GetProperty("Now" ); var (isStatic, isRO, isIndexed, propType) = prop; Console.WriteLine($"\nThe {dateType.FullName} .{prop.Name} property:" ); Console.WriteLine($" PropertyType: {propType.Name} " ); Console.WriteLine($" Static: {isStatic} " ); Console.WriteLine($" Read-only: {isRO} " ); Console.WriteLine($" Indexed: {isIndexed} " ); Type listType = typeof (List<>); prop = listType.GetProperty("Item" , BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); var (hasGetAndSet, sameAccess, accessibility, getAccessibility, setAccessibility) = prop; Console.Write($"\nAccessibility of the {listType.FullName} .{prop.Name} property: " ); if (!hasGetAndSet | sameAccess) { Console.WriteLine(accessibility); } else { Console.WriteLine($"\n The get accessor: {getAccessibility} " ); Console.WriteLine($" The set accessor: {setAccessibility} " ); } } }
참조