매개변수
params 키워드 - C# 참조
params(C# 참조)params (C# Reference) 이 문서의 내용 --> params 키워드를 사용하면 가변 개수의 인수를 사용하는 메서드 매개 변수를 지정할 수 있습니다.By using the params keyword, you can specify a method parameter that takes a variable number of arguments. 매개 변수 선언이나 지정된 형식의 인수 배열에 지정된 형식의 쉼표로 구분된 인수 목
docs.microsoft.com
params 키워드를 사용하면 가변 개수의 인수를 사용하는 메서드 매개 변수를 지정할 수 있습니다.
매개 변수 선언이나 지정된 형식의 인수 배열에 지정된 형식의 쉼표로 구분된 인수 목록을 보낼 수 있습니다. 인수를 보내지 않을 수도 있습니다. 인수를 보내지 않는 경우 params 목록의 길이는 0입니다.
메서드 선언에서 params 키워드 뒤에는 추가 매개 변수가 허용되지 않으며, params 키워드 하나만 메서드 선언에 사용할 수 있습니다.
params 매개 변수의 선언된 형식은 다음 예제와 같이 1차원 배열이어야 합니다. 그렇지 않으면 컴파일러 오류 CS0225가 발생합니다.
예제
다음 예제에서는 params 매개 변수에 인수를 보낼 수 있는 다양한 방법을 보여 줍니다.
C#복사
public class MyClass { public static void UseParams(params int[] list) { for (int i = 0; i < list.Length; i++) { Console.Write(list[i] + " "); } Console.WriteLine(); } public static void UseParams2(params object[] list) { for (int i = 0; i < list.Length; i++) { Console.Write(list[i] + " "); } Console.WriteLine(); } static void Main() { // You can send a comma-separated list of arguments of the // specified type. UseParams(1, 2, 3, 4); UseParams2(1, 'a', "test"); // A params parameter accepts zero or more arguments. // The following calling statement displays only a blank line. UseParams2(); // An array argument can be passed, as long as the array // type matches the parameter type of the method being called. int[] myIntArray = { 5, 6, 7, 8, 9 }; UseParams(myIntArray); object[] myObjArray = { 2, 'b', "test", "again" }; UseParams2(myObjArray); // The following call causes a compiler error because the object // array cannot be converted into an integer array. //UseParams(myObjArray); // The following call does not cause an error, but the entire // integer array becomes the first element of the params array. UseParams2(myIntArray); } } /* Output: 1 2 3 4 1 a test 5 6 7 8 9 2 b test again System.Int32[] */
디폴트 매개변수 주의사항
l 어떤 매개변수에 기본값을 지정하면 뒤쪽 파라미터도 전부 기본값을 해야한다.
l 기본값들은 컴파일 시점에 모두 알 수 있는 상수 값이어야 한다.
l 매개변수의 이름을 직접 지정 – 임의로 변경하지 X
l 기본값 변경 X
l Ref, out 는 기본값 지정 X – 의미 있는 기본값 전달 안 됨
l Var 타입 변수 사용 X
+ var 와 dynamic의 차이점
전자는 문법적인 단축 방법일 뿐, 컴파일러가 실제 타입을 유추하도록 명령하는 것
후자는 지역 변수, 필드, 매개변수 사용 가능, 이미 완성된(컴파일 후) 인스턴스에 활용.
Ref와 out의 차이
둘은 CLR, IL 상에서 같은 역할을 한다. 단, ref를 문법적으로 맞는지 검사를 한다.
초기화되지 않은 변수를 전달하려고 하면 오류가 난다.
Params 키워드
가변 매개변수 전달의 경우 사용
params Object[] objects 식으로 사용하면 기정 거의 모든 타입을 매개변수로 받을 수 있다.
단, 가변으로 하게 되도 결국 추가적인 성능저하를 초래한다. 매개변수가 많이 할당되는 만큼 힙에 할당하는 것이다.
상수화
C++ 은 변수들에 상수화를 지원하지만 C#에서는 그렇지 못하다. 이유는 CLR이 지원하지 않기 때문.
CLR이 상수화를 허용한다면 매 객체에 대해 쓰기 작업이 발생했는지 확인해야만 하며, 이로 인해 개발자들에게는 복잡성, 성능에는 치명적인 저하가 발생할 것이기 때문이다.
프로퍼티
속성 - C# 프로그래밍 가이드
속성(C# 프로그래밍 가이드)Properties (C# Programming Guide) 이 문서의 내용 --> 속성은 전용 필드의 값을 읽거나 쓰거나 계산하는 유연한 메커니즘을 제공하는 멤버입니다.A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. 공용 데이터 멤버인 것처럼 속성을 사용할 수 있지만,
docs.microsoft.com
속성은 전용 필드의 값을 읽거나 쓰거나 계산하는 유연한 메커니즘을 제공하는 멤버입니다. 공용 데이터 멤버인 것처럼 속성을 사용할 수 있지만, 실제로 접근자라는 특수 메서드입니다. 이렇게 하면 데이터에 쉽게 액세스할 수 있으며 메서드의 안전성과 유연성 수준을 올리는 데에도 도움이 됩니다.
속성 개요
-
속성을 사용하면 클래스가 구현 또는 검증 코드를 숨기는 동시에 값을 가져오고 설정하는 방법을 공개적으로 노출할 수 있습니다.
-
get 속성 접근자는 속성 값을 반환하는 데 사용되고 set 속성 접근자는 새 값을 할당하는 데 사용됩니다. 이러한 접근자는 각기 다른 액세스 수준을 가질 수 있습니다. 자세한 내용은 접근자 액세스 가능성 제한을 참조하세요.
-
value 키워드는 set 접근자가 할당하는 값을 정의하는 데 사용됩니다.
-
속성은 읽기/쓰기(get 및 set 접근자 모두 포함), 읽기 전용(get 접근자는 포함하지만 set 접근자는 포함 안 함) 또는 쓰기 전용(set 접근자는 포함하지만 get 접근자는 포함 안 함)일 수 있습니다. 쓰기 전용 속성은 거의 없으며 주로 중요한 데이터에 대한 액세스를 제한하는 데 사용됩니다.
-
사용자 지정 접근자 코드가 필요 없는 단순한 속성은 식 본문 정의나 자동 구현 속성으로 구현할 수 있습니다.
지원 필드가 있는 속성
속성을 구현하는 한 가지 기본 패턴에는 private 지원 필드를 사용하여 속성 값을 설정 및 검색하는 작업이 포함됩니다. get 접근자는 private 필드의 값을 반환하고 set 접근자는 private 필드에 값을 할당하기 전에 데이터 유효성 검사를 수행할 수 있습니다. 또한 두 접근자 모두 데이터를 저장 또는 반환하기 전에 데이터에 대한 변환이나 계산을 수행할 수도 있습니다.
다음 예제에서 이 방법을 보여 줍니다. 이 예제에서 TimePeriod 클래스는 시간 간격을 나타냅니다. 내부적으로 이 클래스는 _seconds라는 private 필드에 시간 간격을 초 단위로 저장합니다. Hours라는 읽기/쓰기 속성을 사용하면 고객이 시간 간격을 시간 단위로 지정할 수 있습니다. get 및 set 접근자 모두 필요에 따라 시간 및 초 간의 변환을 수행합니다. 또한 set 접근자는 데이터의 유효성을 검사하고 시간(시)이 잘못된 경우 ArgumentOutOfRangeException을 throw합니다.
C#복사
using System; class TimePeriod { private double _seconds; public double Hours { get { return _seconds / 3600; } set { if (value < 0 || value > 24) throw new ArgumentOutOfRangeException( $"{nameof(value)} must be between 0 and 24."); _seconds = value * 3600; } } } class Program { static void Main() { TimePeriod t = new TimePeriod(); // The property assignment causes the 'set' accessor to be called. t.Hours = 24; // Retrieving the property causes the 'get' accessor to be called. Console.WriteLine($"Time in hours: {t.Hours}"); } } // The example displays the following output: // Time in hours: 24
식 본문 정의
속성 접근자는 식의 결과를 할당하거나 반환하기만 하는 한 줄로 된 문으로 구성되는 경우가 많습니다. 이러한 속성은 식 본문 멤버로 구현할 수 있습니다. 식 본문 정의는 => 기호와 속성에 할당하거나 속성에서 검색할 식으로 구성됩니다.
C# 6부터 읽기 전용 속성에서 get 접근자를 식 본문 멤버로 구현할 수 있습니다. 이 경우 get 접근자 키워드나 return 키워드를 모두 사용하지 않습니다. 다음 예제에서는 읽기 전용 Name 속성을 식 본문 멤버로 구현합니다.
C#복사
using System; public class Person { private string _firstName; private string _lastName; public Person(string first, string last) { _firstName = first; _lastName = last; } public string Name => $"{_firstName} {_lastName}"; } public class Example { public static void Main() { var person = new Person("Magnus", "Hedlund"); Console.WriteLine(person.Name); } } // The example displays the following output: // Magnus Hedlund
C# 7.0부터 get 및 set 접근자 모두를 식 본문 멤버로 구현할 수 있습니다. 이 경우 get 및 set 키워드가 있어야 합니다. 다음 예제에서는 두 접근자에 대해 식 본문 정의를 사용하는 방법을 보여 줍니다. return 키워드는 get 접근자와 함께 사용하지 않습니다.
C#복사
using System; public class SaleItem { string _name; decimal _cost; public SaleItem(string name, decimal cost) { _name = name; _cost = cost; } public string Name { get => _name; set => _name = value; } public decimal Price { get => _cost; set => _cost = value; } } class Program { static void Main(string[] args) { var item = new SaleItem("Shoes", 19.95m); Console.WriteLine($"{item.Name}: sells for {item.Price:C2}"); } } // The example displays output like the following: // Shoes: sells for $19.95
자동으로 구현된 속성
경우에 따라 get 속성과 set 접근자에서 지원 필드에 값을 할당하거나 지원 필드에서 값을 검색하기만 하고 추가 논리를 포함하지 않을 수 있습니다. 자동 구현 속성을 사용하면 코드를 간소화할 수 있을 뿐 아니라 C# 컴파일러에서 지원 필드를 투명하게 제공하도록 할 수 있습니다.
속성에 get 및 set 접근자가 모두 포함된 경우 두 접근자를 모두 자동 구현해야 합니다. 구현을 제공하지 않고 get 및 set 키워드를 사용하여 자동 구현 속성을 정의합니다. 다음 예제에서는 Name 및 Price가 자동 구현 속성인 점만 제외하고 이전 예제와 동일합니다. 이 예제에서는 매개 변수화된 생성자도 제거하므로 이제 SaleItem 개체가 매개 변수 없는 생성자 및 개체 이니셜라이저에 대한 호출을 통해 초기화됩니다.
C#복사
using System; public class SaleItem { public string Name { get; set; } public decimal Price { get; set; } } class Program { static void Main(string[] args) { var item = new SaleItem{ Name = "Shoes", Price = 19.95m }; Console.WriteLine($"{item.Name}: sells for {item.Price:C2}"); } } // The example displays output like the following: // Shoes: sells for $19.95
자동 구현 속성(Automatically Implemented Property, AIP)
프로퍼티를 정의하면서 get과 set 메서드의 구현부를 생략하면, C# 컴파일러는 자동으로 프로퍼티와 연결되는 private필드를 정의해준다.
단점
l 값을 초기화할 방법이 없다.
l 스트림에 serialize할 시 필드 이름에 의존하게 되는데, 타입을 serialize를 하면 매 컴파일 마다 이름이 바뀌게 되어 스트림으로 복원할 수 없게 된다.
l 중단점을 추가할 수 없다.
l 실행이 오래 걸리는 점 때문에 스레드 동기화에는 메서드를 사용해야 한다.
l 한 줄에서 여러 번 호출할 경우 – 프로퍼티는 매번 다른 값을 반환하지만, 필드는 같은 값을 반환한다.
l 객체 상태와는 무관하게 추가적인 메모리 요구, 다른 객체를 반환이 가능
필드는 항상 원천 객체 상태를 나타내는 참조를 반환
l 제네릭 사용 불가. 실은 개념적으로 맞지 않다. 객체의 상태와 무관하게 완전 독릭적인 행위를 하진 않는다.
'C# > CLR via' 카테고리의 다른 글
인터페이스 (0) | 2020.03.25 |
---|---|
이벤트 & 제네릭 (0) | 2020.02.28 |
메서드 (0) | 2020.02.19 |
참조 타입과 값 타입 (0) | 2020.02.18 |
Object 그리고 캐스팅 (0) | 2020.02.16 |