C# 키워드 O~S 프로그래밍/C#2016. 5. 31. 15:46
object
1. object 형식은 .NET Framework의 Object에 대한 별칭입니다.
2. C#의 통합된 형식 시스템에서는 미리 정의된 형식과 사용자가 정의한 형식, 참조 형식과 값 형식 같은 모든 형식에 Object에서 직접 또는 간접적으로 상속됩니다.
3. object 형식의 변수에는 모든 형식의 값을 할당할 수 있습니다.
4. 값 형식의 변수를 object 형식으로 변환하는 경우 이를 boxing이라고 합니다.
5. object 형식의 변수를 값 형식으로 변환하는 경우 이를 unboxing이라고 합니다.
6. 자세한 내용은 Boxing 및 Unboxing을 참조하십시오.
7. 다음 예제에서는 object 형식 변수에서 임의의 데이터 형식 값을 수용하는 방법과 object 형식 변수가 .NET Framework에서 Object 메서드를 사용하는 방법에 대해 보여 줍니다.
class ObjectTest { public int i = 10; } class MainClass2 { static void Main() { object a; a = 1; // an example of boxing Console.WriteLine(a); Console.WriteLine(a.GetType()); Console.WriteLine(a.ToString()); a = new ObjectTest(); ObjectTest classRef; classRef = (ObjectTest)a; Console.WriteLine(classRef.i); } } /* Output 1 System.Int32 1 * 10 */
operator
1. operator 키워드를 사용하여 기본 제공 연산자(a built-in operator)를 오버로드하거나 클래스 또는 구조체 선언에 사용자 정의 변환을 제공할 수 있습니다.
2. 아래 예제는 매우 간단한 분수 클래스(a very simplified class for fractional numbers)입니다.
3. 이 클래스는 + 및 * 연산자를 오버로드하여 분수 더하기(fractional addition)와 곱하기(multiplication)를 수행하고 Fraction 형식을 Double 형식으로 변환하는 변환 연산자도 제공합니다.
class Fraction { int num, den; public Fraction(int num, int den) { this.num = num; this.den = den; } // overload operator + public static Fraction operator +(Fraction a, Fraction b) { return new Fraction(a.num * b.den + b.num * a.den, a.den * b.den); } // overload operator * public static Fraction operator *(Fraction a, Fraction b) { return new Fraction(a.num * b.num, a.den * b.den); } // user-defined conversion from Fraction to double public static implicit operator double(Fraction f) { return (double)f.num / f.den; } } class Test { static void Main() { Fraction a = new Fraction(1, 2); Fraction b = new Fraction(3, 7); Fraction c = new Fraction(2, 3); Console.WriteLine((double)(a * b + c)); } } /* Output 0.880952380952381 */
out
1. out 컨텍스트 키워드(contextual keyword)는 두 가지 컨텍스트, 즉 매개 변수 한정자로 사용하거나 인터페이스와 대리자의 제네릭 형식 매개 변수 선언에서 사용할 수 있습니다.
2. 이 항목에서는 매개 변수 한정자에 대해 설명하며, 이 항목에서 제네릭 형식 매개 변수 선언에 대한 정보를 확인할 수 있습니다.
3. out 키워드를 사용하면 참조를 통해 인수(arguments)를 전달(to be passed)할 수 있습니다
4. 이러한 방식은 ref 키워드와 비슷합니다.
5. 단, ref의 경우에는 변수를 전달하기 전에 초기화해야 합니다.
6. out 매개 변수를 사용하려면 메서드 정의(the method definition)와 호출 메서드(the calling method)가 모두 명시적으로 out 키워드를 사용해야 합니다.
class OutExample { static void Method(out int i) { i = 44; } static void Main() { int value; Method(out value); // value is now 44 } }
7. out 인수로 전달되는 변수는 전달하기 전에 초기화할 필요가 없지만 호출되는 메서드는 반환되기 전에 값을 할당해야 합니다.
8. ref 및 out 키워드는 서로 다른 런타임 동작을 수행하지만 컴파일 타임에 메서드 시그니처의 일부로 간주되지는 않습니다.
9. 따라서 메서드 하나는 ref 인수를 사용하고 다른 하나는 out 인수를 사용하는 것 외에는 차이점이 없으면 메서드를 오버로드할 수 없습니다.
10. 예를 들어 다음 코드는 컴파일되지 않습니다.
class CS0663_Example { // Compiler error CS0663: "Cannot define overloaded // methods that differ only on ref and out". public void SampleMethod(out int i) { } public void SampleMethod(ref int i) { } }
11. 그러나 다음과 같이 메서드 하나는 ref 또는 out 인수를 사용하고 다른 하나는 인수를 사용하지 않는 경우에는 오버로드를 수행할 수 있습니다.
class OutOverloadExample { public void SampleMethod(int i) { } public void SampleMethod(out int i) { i = 5; } }
12. 속성(properties)은 변수가 아니므로 out 매개 변수로 전달할 수 없습니다.
13. 배열 전달에 대한 자세한 내용은 ref 및 out을 사용하여 배열 전달을 참조하십시오.
14. ref 및 out 키워드는 다음의 경우와 같은 메소드에서 사용할 수 없습니다.
1) 비동기 한정자(async modifier)를 사용하여 정의된 비동기 메소드(async methods)
2) yield return 또는 yield break 문을 포함하는 반복기 메서드(iterator methods)
15. 메서드가 여러 값을 반환하도록 하려는 경우에는 out 메서드를 선언하면 유용합니다.
16. 다음 예제에서는 out을 사용하여 단일 메서드 호출로(with a single method call) 3개 변수를 반환합니다.
17. 세 번재 인수(the third argument)는 null에 할당됩니다.
18. 따라서 메서드가 값을 선택적으로(optionally) 반환할 수 있습니다.
class OutReturnExample { static void Method(out int i, out string s1, out string s2) { i = 44; s1 = "I've been returned"; s2 = null; } static void Main() { int value; string str1, str2; Method(out value, out str1, out str2); // value is now 44 // str1 is now "I've been returned" // str2 is (still) null; } }
out (제네릭 한정자)
1. 제네릭 형식 매개 변수의 경우 out 키워드는 형식 매개 변수가 공변(covariant)임을 나타냅니다.
2. 제네릭 인터페이스와 대리자에서 out 키워드를 사용할 수 있습니다.
3. 공 분산(covariance)을 사용하면 제네릭 매개 변수로 지정된 형식보다 더 많이 파생된 형식을 사용할 수 있습니다.
4. 이 경우 variant 인터페이스를 구현하는 클래스의 암시적 변환과 대리자 형식의 암시적 변환이 가능합니다.
5. 공 분산(covariance) 및 반공 분산(contravariance)은 참조 형식에만 지원되고 값 형식에는 지원되지 않습니다.
6. 공변(covariant) 형식 매개 변수가 있는 인터페이스의 메서드는 형식 매개 변수로 지정된 형식보다 더 많이 파생된 형식을 반환할 수 있습니다.
7. 예를 들어 .NET Framework 4의 IEnumerable<T>에서 형식 T가 공변(covariant)이므로 특수 변환 메서드를 사용하지 않고도 IEnumerable(Of String) 형식의 개체를 IEnumerable(Of Object) 형식의 개체에 할당할 수 있습니다.
8. 공변 대리자는 같은 형식이지만 더 많이 파생된 제네릭 형식 매개 변수를 사용하는 다른 대리자에게 할당할 수 있습니다.
8. 자세한 내용은 공 분산 및 반공 분산을 참조하십시오.
9. 다음 예제에서는 공변(covariant) 제네릭 인터페이스를 선언, 확장(extend) 및 구현하는 방법을 보여 줍니다.
10. 공변 인터페이스를 구현하는 클래스의 암시적 변환을 사용하는 방법도 보여줍니다.
// Covariant interface. interface ICovariant<out R> { } // Extending covariant interface. interface IExtCovariant<out R> : ICovariant<R> { } // Implementing covariant interface. class Sample<R> : ICovariant<R> { } class Program { static void Test() { ICovariant<Object> iobj = new Sample<Object>(); ICovariant<String> istr = new Sample<String>(); // You can assign istr to iobj because // the ICovariant interface is covariant. iobj = istr; } }
11. 제네릭 인터페이스에서 다음 조건을 충족하는 경우 형식 매개 변수를 공변(covariant)으로 선언할 수 있습니다.
1) 형식 매개 변수가 인터페이스 메서드의 반환 형식으로만 사용되고 메서드 인수의 형식으로 사용 되지 않는 경우
참고 |
---|
그러나 이 규칙에는 한 가지 예외가 있습니다. 공변(covariant) 인터페이스에서 반공변(contravariant) 제네릭 대리자가 메서드 매개 변수인 경우에는 공변(covariant) 형식을 이 대리자에 대한 제네릭 형식 매개 변수로 사용할 수 있습니다. 공변(covariant) 및 반공변(contravariant) 제네릭 대리자에 대한 자세한 내용은 대리자의 가변성(C# 및 Visual Basic) 및 Func 및 Action 제네릭 대리자에 가변성 사용(C# 및 Visual Basic)을 참조하십시오 |
2) 형식 매개 변수가 인터페이스 메서드에 대한 제네릭 제약 조건으로 사용되지 않는 경우
12. 다음 예제에서는 공변(covariant) 제네릭 대리자를 선언, 인스턴스화 및 호출하는 방법을 보여줍니다.
13. 대리자 형식을 암시적으로 변환하는 방법도 보여줍니다.
// Covariant delegate. public delegate R DCovariant<out R>(); // Methods that match the delegate signature. public static Control SampleControl() { return new Control(); } public static Button SampleButton() { return new Button(); } public void Test() { // Instantiate the delegates with the methods. DCovariant<Control> dControl = SampleControl; DCovariant<Button> dButton = SampleButton; // You can assign dButton to dControl // because the DCovariant delegate is covariant. dControl = dButton; // Invoke the delegate. dControl(); }
14. 메서드 반환 형식으로만 사용되고 메서드 인수로는 사용되지 않는 형식의 경우 제네릭 대리자에서 해당 형식을 공변(covariant)으로 선언할 수 있습니다.\
override
1. override 한정자는 상속된 메서드, 속성, 인덱서 또는 이벤트의 추상 또는 가상 구현을 확장하거나 수정하는 데 필요합니다.
2. 이 예제에서 Area 추상 ShapeClass에서 상속되므로 Square 클래스는 Area의 재정의된 구현(overridden implementation)을 제공해야 합니다.
abstract class ShapesClass { abstract public int Area(); } class Square : ShapesClass { int side = 0; public Square(int n) { side = n; } // Area method is required to avoid // a compile-time error. public override int Area() { return side * side; } static void Main() { Square sq = new Square(12); Console.WriteLine("Area of the square = {0}", sq.Area()); } interface I { void M(); } abstract class C : I { public abstract void M(); } } // Output: Area of the square = 144
3. override 메서드는 기본 클래스에서 상속된 멤버를 새로 구현합니다.
4. override 선언에 의해 재정의된 메서드를 재정의된 기본 메서드라고 합니다.
5. 재정의된 기본 메서드의 시그니처는 override 메서드의 시그니처와 같아야 합니다.
6. 삭속에 대한 자세한 내용은 상속을 참조하십시오.
7. 비 가상(non-virtual) 메서드 또는 정적(static) 메서드는 재정의할 수 없습니다.
8. 재정의된 기본 메서드는 virtual, abstract 또는 override 메서드이어야 합니다.
9. override 선언을 사용하여 virtual 메서드의 액세스 가능성(accessibility)을 변경할 수 없습니다.
10. override 메서드와 virtual 메서드의 액세스 수준 한정자는 모두 동일합니다.
11. new, static 또는 virtual 한정자를 사용하여 override 메서드를 한정할 수 없습니다.
12. 속성 선언을 재정의할 때는 상속된 속성과 동일한 액세스 한정자, 형식 및 이름을 정확히(exactly) 지정해야 하며 재정의된 속성은 virtual, abstract 또는 override여야 합니다.
13. override 키워드를 사용하는 방법에 대한 자세한 내용은 Override 및 New 키워드를 사용하여 버전 관리 및 Override 및 New 키워드를 사용해야 하는 경우를 참조하십시오.
14. 이 예제에서는 Employee라는 기본 클래스와 SalesEmployee라는 파생 클래스를 정의합니다.
15. SalesEmployee 클래스는 추가 속성 salesbonus를 포함하여 이를 고려하여(in order to take it int account) CalculatePay 메서드를 재정의합니다.
class TestOverride { public class Employee { public string name; // Basepay is defined as protected, so that it may be // accessed only by this class and derrived classes. protected decimal basepay; // Constructor to set the name and basepay values. public Employee(string name, decimal basepay) { this.name = name; this.basepay = basepay; } // Declared virtual so it can be overridden. public virtual decimal CalculatePay() { return basepay; } } // Derive a new class from Employee. public class SalesEmployee : Employee { // New field that will affect the base pay. private decimal salesbonus; // The constructor calls the base-class version, and // initializes the salesbonus field. public SalesEmployee(string name, decimal basepay, decimal salesbonus) : base(name, basepay) { this.salesbonus = salesbonus; } // Override the CalculatePay method // to take bonus into account. public override decimal CalculatePay() { return basepay + salesbonus; } } static void Main() { // Create some new employees. SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500); Employee employee2 = new Employee("Bob", 1200); Console.WriteLine("Employee4 " + employee1.name + " earned: " + employee1.CalculatePay()); Console.WriteLine("Employee4 " + employee2.name + " earned: " + employee2.CalculatePay()); } } /* Output: Employee4 Alice earned: 1500 Employee4 Bob earned: 1200 */
params
1. params 키워드를 사용하면 여러 개의 인수를 사용하는(takes a variable number of arguments) 메서드 매개 변수를 지정할 수 있습니다.
2. 매개 변수 선언에 지정된 형식의 쉼표로 구분된 인수 목록(a comma-separated list of arguments) 또는 지정된 형식의 인수 배열을 보낼 수 있습니다.
3. 인수 없이 보낼 수도 있습니다.
4. 인수를 보내지 않으면 params 목록의 길이는 0입니다.
5. 메서드 선언에서 params 키워드 다음에는 매개 변수를 추가할 수 없으며, params 키워드 하나만 메서드 선언에 사용할 수 있습니다(is permitted).
6. 다음 예제에서는 params 매개 변수에 인수를 보낼 수 있는 다양한 방법을 보여 줍니다.
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[] */
private
1. private 키워드는 멤버 액세스 한정자입니다.
2. private 액세스는 허용도가 가장 낮은 액세스 수준입니다(the least permissive access level).
3. private 멤버는 다음 예제처럼 해당 멤버가 선언되어 있는 클래스 또는 구조체의 본문 내에서만 액세스할 수 있습니다.
class Employee { private int i; double d; // private access by default }
4. 동일한 본문에서 중첩된 형식(nested types)도 이 private 멤버에 액세스할 수 있습니다.
5. private 멤버가 선언되어 있는 클래스 또는 구조체 외부에서 이 멤버를 참조(reference)하면 컴파일 타임 오류가 발생합니다.
6. private을 다른 액세스 한정자와 비교하려면 액세스 가능성 수준 및 액세스 한정자를 참조하십시오.
7. 이 예제에서 Employee 클래스에는 name과 salary라는 두 개의 전용(private) 데이터 멤버가 포함되어 있습니다.
8. 이들은 private 멤버이므로 멤버 메서드를 사용해야만 액세스할 수 있습니다.
9. private 멤버에 대한 액세스를 제어할 수 있도록 GetName 및 Salary라는 public 메서드가 추가됩니다.
10. name 멤버에는 public 메서드를 사용하여 액세스하고, salary 멤버에는 public 읽기 전용 속성을 통해 액세스합니다.
11. 자세한 내용은 속성을 참조하십시오.
class Employee2 { private string name = "FirstName, LastName"; private double salary = 100.0; public string GetName() { return name; } public double Salary { get { return salary; } } } class PrivateTest { static void Main() { Employee2 e = new Employee2(); // The data members are inaccessible (private), so // they can't be accessed like this: // string n = e.name; // double s = e.salary; // 'name' is indirectly accessed via method: string n = e.GetName(); // 'salary' is indirectly accessed via property double s = e.Salary; } }
protected
1. protected 키워드는 멤버 액세스 한정자입니다.
2. 보호된 멤버는 해당 클래스 내에서와 파생 클래스 인스턴스에서 액세스할 수 있습니다.
3. 다른 액세스 한정자와 protected를 비교하려면 액세스 가능성 수준을 참조하십시오.
4. 기본 클래스의 보호된 멤버를 파생 클래스에서 액세스할 수 있는 경우는 해당 파생 클래스 형식을 통해 액세스하는 경우뿐입니다.
5. 예를 들어 다음의 코드 세그먼트를 참조하십시오.
class A { protected int x = 123; } class B : A { static void Main() { A a = new A(); B b = new B(); // Error CS1540, because x can only be accessed by // classes derived from A. // a.x = 10; // OK, because this class derives from A. b.x = 10; } }
6. a.x = 10 문은 클래스 B의 인스턴스가 아니라 정적 메서드인 Main 내에서 만들어지므로 오류를 생성합니다.
7. 구조체는 상속되지 않으므로 구조체 멤버는 보호될 수 없습니다.
8. 이 예제의 경우 DerivedPoint 클래스는 Pint에서 파생됩니다.
9. 따라서 파생된 클래스에서 기본 클래스의 보호된 멤버에 직접 액세스할 수 있습니다.
class Point { protected int x; protected int y; } class DerivedPoint: Point { static void Main() { DerivedPoint dpoint = new DerivedPoint(); // Direct access to protected members: dpoint.x = 10; dpoint.y = 15; Console.WriteLine("x = {0}, y = {1}", dpoint.x, dpoint.y); } } // Output: x = 10, y = 15
10. x 및 y의 액세스 수준을 private으로 변경하면 컴파일러 오류 메시지를 생성합니다(issue).
'Point.y' is inaccessible due to its protection level.
'Point.x' is inaccessible due to its protection level.
public
1. public 키워드는 형식 및 형식 멤버에 대한 액세스 한정자입니다.
2. public 액세스는 허용도가 가장 높은 액세스 수준입니다(the most permissive access leve).
3. 다음 예제처럼 public 멤버는 액세스에 제한이 없습니다(no restrictions on accessing).
class SampleClass { public int x; // No access restrictions. }
4. 자세한 내용은 액세스 한정자 및 액세스 가능성 수준을 참조하십시오.
5. 다음 예제에서는 두 개의 클래스 PointTest 및 MainClass가 선언되어 있습니다.
6. PointTest의 public 멤버인 x 및 y에는 MainClass에서 직접 액세스할 수 있습니다.
class PointTest { public int x; public int y; } class MainClass4 { static void Main() { PointTest p = new PointTest(); // Direct access to public members: p.x = 10; p.y = 15; Console.WriteLine("x = {0}, y = {1}", p.x, p.y); } } // Output: x = 10, y = 15
7. public 액세스 수준을 private 또는 protected로 변경하면 다음과 같은 오류 메시지가 나타납니다.
8. 보호 수준 때문에 Pointtest.y에 액세스할 수 없습니다.
readonly
1. readonly 키워드는 필드에 사용할 수 있는 한정자입니다.
2. 필드 선언에 readonly 한정자가 포함되어 있으면 선언의 일부로 대입하거나 동일한 클래스의 생성자에서 대입하는 경우에만 선언을 통해 정의한 필드에 값을 대입할 수 있습니다.
3. 이 예제에서 year 필드는 클래스 생성자에서 값이 할당된 경우라도 ChangeYear 메서드로 값을 변경할 수 없습니다.
class Age { readonly int _year; Age(int year) { _year = year; } void ChangeYear() { //_year = 1967; // Compile error if uncommented. } }
4. 다음 경우에만 readonly 필드에 값을 대입할 수 있습니다.
public readonly int y = 5;
5. 인스턴스 필드의 경우 필드 선언이 포함된 클래스의 인스턴스 생성자에서 값을 대입할 수 있으며, 정적 필드의 경우에는 필드 선언이 포함된 클래스의 정적 생성자에서 값을 대입할 수 있습니다.
6. 위의 두 경우는 readonly 필드를 out 또는 ref 매개 변수로 전달할 수 있는 유일한 경우이기도 합니다.
참고 |
---|
readonly 키워드는 const 키워드와 다릅니다. const 필드는 필드를 선언할 때만 초기화될 수 있습니다. readonly 필드는 필드를 선언할 때 또는 생성자에서 초기화될 수 있습니다. 따라서 readonly 필드의 값은 사용된 생성자에 따라 다릅니다. 또한 const 필드는 컴파일 타임 상수인 반면 readonly필드는 다음 예제에서와 같이 런타임 상수로도 사용할 수 있습니다. |
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
public class ReadOnlyTest { class SampleClass { public int x; // Initialize a readonly field public readonly int y = 25; public readonly int z; public SampleClass() { // Initialize a readonly instance field z = 24; } public SampleClass(int p1, int p2, int p3) { x = p1; y = p2; z = p3; } } static void Main() { SampleClass p1 = new SampleClass(11, 21, 32); // OK Console.WriteLine("p1: x={0}, y={1}, z={2}", p1.x, p1.y, p1.z); SampleClass p2 = new SampleClass(); p2.x = 55; // OK Console.WriteLine("p2: x={0}, y={1}, z={2}", p2.x, p2.y, p2.z); } } /* Output: p1: x=11, y=21, z=32 p2: x=55, y=25, z=24 */
7. 앞의 예제에서 다음과 같은 문을 사용하면
p2.y = 66; // 오류
8. 다음과 같은 컴파일러 오류가 메시지가 발생합니다.
The left-hand side of an assignment must be an l-value
9. 이 오류는 상수에 값을 대입할 때 발생하는 오류와 동일합니다.
ref
1. ref 키워드는 인수(argument)가 값의 복사가 아닌 참조로 전달되도록 합니다.
2. 인수를 참조로 전달하는 경우 호출된 메서드의 매개 변수 변경 내용이 호출 메서드에 반영됩니다(is reflected in the calling method).
3. 예를 들어 호출자가 로컬 변수 식 또는 배열 요소 액세스 식을 전달하는 경우 호출된 메서드에서 ref 매개 변수가 참조하는 개체를 바꾸면 호출자의 로컬 변수 또는 배열 요소가 새 개체를 참조합니다.
참고 |
---|
4. ref 매개 변수를 사용하려면, 다음 예제처럼 메서드 정의와 메서드 호출 양쪽 모두 ref 키워드를 명시적으로 사용해야 합니다.
class RefExample { static void Method(ref int i) { // Rest the mouse pointer over i to verify that it is an int. // The following statement would cause a compiler error if i // were boxed as an object. i = i + 44; } static void Main() { int val = 1; Method(ref val); Console.WriteLine(val); // Output: 45 } }
5. ref 매개 변수와 전달되는 인수는 전달되기 전에 초기화해야 합니다.
6. 이러한 방식은 인수를 전달하기 전에 명시적으로 초기화할 필요가 없는 out 매개변수와는 다릅니다.
7. 자세한 내용은 out을 참조하세요.
8. 클래스의 멤버는 ref 및 out 만 다른 서명을 포함할 수 없습니다.
9. 특정 형식의 두 멤버가 하나는 ref 매개 변수를 포함하고 다른 하나는 out 매개 변수를 포함한다는 것 외에는 차이가 없으면 컴파일러 오류가 발생합니다.
10. 예를 들어 다음 코드는 컴파일되지 않습니다.
class CS0663_Example { // Compiler error CS0663: "Cannot define overloaded // methods that differ only on ref and out". public void SampleMethod(out int i) { } public void SampleMethod(ref int i) { } }
11. 그러나 한쪽 메서드에 ref 또는 out 매개 변수가 한 개 있고, 다른 쪽에 값 매개 변수가 한 개 있을 경우, 다음 예제와 같이 오버로딩될 수 있습니다.
class RefOverloadExample { public void SampleMethod(int i) { } public void SampleMethod(ref int i) { } }
12. 숨기기(hiding)나 재정의(overring)과 같이 시그니처가 필요한 다른 상황에서는 ref 및 out이 서명의 일부가 되며 서로 일치하지 않습니다.
13. 속성(properties)은 변수가 아니라 메서드이며 ref 매개 변수로 전달할 수 없습니다.
14. 배열을 전달하는 방법에 대한 자세한 내용은 ref 및 out을 사용하여 배열 전달을 참조하세요.
15. ref 및 out 키워드는 다음의 경우와 같은 메소드에서 사용할 수 없습니다.
1) 비동기(async) 한정자를 사용하여 정의된 비동기(async) 메서드
2) yield return 또는 yield break 문을 포함하는 반복기 메서드
16. 위의 예제에서는 값 형식을 참조로 전달하는 경우의 결과를 보여줍니다.
17. ref 키워드를 사용하여 참조 형식을 전달할 수도 있습니다.
18. 참조 형식을 참조로 전달하는 경우 호출된 메서드는 참조 매개 변수가 참조하는 호출 메서드의 개체를 바꿀 수 있습니다.
19. 개체의 저장 위치는 참조 매개변수의 값으로 메서드에 전달됩니다.
20. 매개 변수의 저장 위치에서 값을 변경하여 새 개체를 가리키도록 하면 호출자가 참조하는 저장 위치도 변경됩니다.
21. 다음 예제에서는 참조 형식 인스턴스를 ref 매개 변수로 전달합니다.
22. 참조 형식을 값 및 참조로 전달하는 방법에 대한 자세한 내용은 참조 형식 매개 변수 전달을 참조하세요.
class RefExample2 { static void ChangeByReference(ref Product itemRef) { // The following line changes the address that is stored in // parameter itemRef. Because itemRef is a ref parameter, the // address that is stored in variable item in Main also is changed. itemRef = new Product("Stapler", 99999); // You can change the value of one of the properties of // itemRef. The change happens to item in Main as well. itemRef.ItemID = 12345; } static void Main() { // Declare an instance of Product and display its initial values. Product item = new Product("Fasteners", 54321); System.Console.WriteLine("Original values in Main. Name: {0}, ID: {1}\n", item.ItemName, item.ItemID); // Send item to ChangeByReference as a ref argument. ChangeByReference(ref item); System.Console.WriteLine("Back in Main. Name: {0}, ID: {1}\n", item.ItemName, item.ItemID); } } class Product { public Product(string name, int newID) { ItemName = name; ItemID = newID; } public string ItemName { get; set; } public int ItemID { get; set; } } // Output: //Original values in Main. Name: Fasteners, ID: 54321 //Back in Main. Name: Stapler, ID: 12345
return
1. return 문은 자신이 속한 메서드의 실행을 종료하고 호출한 메서드로 제어를 반환합니다.
2. 선택적 값을 반환할 수도 있습니다.
3. void 형식의 메서드인 경우 return 문을 생략(omit)할 수 있습니다.
4. return 문이 try 블록 내부에 있을 경우 finally 블록이 존재한다면 호출 메서드로 컨트롤을 반환하기 전에 해당 블록이 실행됩니다.
class ReturnTest { static double CalculateArea(int r) { double area = r * r * Math.PI; return area; } static void Main() { int radius = 5; double result = CalculateArea(radius); Console.WriteLine("The area is {0:0.00}", result); // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } // Output: The area is 78.54
sbyte
1. sbyte 키워드는 다음 표에 표시된 크기와 범위에 따라 값을 저장하는 정수 계열
형식 | 범위 | 크기 | .NET Framework 형식 |
---|---|---|---|
sbyte | -128 ~ 127 | 부호 있는 8비트 정수 |
2. 다음과 같은 방식(in this manner)으로 sbyte 변수를 선언하고 초기화할 수 있습니다.
sbyte sByte1 = 127;
3. 앞의 선언에서 정수 리터럴 127은 암시적으로 int에서 sbyte로 변환됩니다.
4. 정수 리터럴이 sbyte 범위를 초과하면 컴파일 오류(a compilation error)가 발생합니다.
5. 오버로드된 메서드를 호출하는 경우 캐스트를 사용해야 합니다.
6. 예를 들어 다음과 같이 sbyte 및 int 매개 변수를 사용하는 오버로드된 메서드가 있습니다.
public static void SampleMethod(int i) {} public static void SampleMethod(sbyte b) {}
7. 이 경우, sbyte 캐스트를 사용하면 올바른 형식이 호출됩니다. 예를 들면 다음과 같습니다.
// Calling the method with the int parameter: SampleMethod(5); // Calling the method with the sbyte parameter: SampleMethod((sbyte)5);
8. sbyte에서 short, int, long, float, double 또는 decimal로의 미리 정의된 암시적 변환이 있습니다.
9. 저장 크기가 더 큰 비 리터럴 숫자 형식(nonliteral numeric types)은 암시적으로 sbyte로 변환할 수 없습니다.
10. 정수 계열 형식의 저장 크기에 대해서는 정수 계열 형식 표를 참조하십시오.
11. 예를 들어 다음과 같은 두 개의 sbyte 변수 x 및 y가 있습니다.
sbyte x = 10, y = 20;
12. 다음 할당문의 경우 할당 연산자의 오른쪽에 있는 산술식이 기본적으로 int로 계산되므로 컴파일 오류가 발생합니다.
sbyte z = x + y; // Error: conversion from int to sbyte
13. 이 문제를 해결하려면 식을 다음의 예제와 같이 캐스팅합니다.
sbyte z = (sbyte)(x + y); // OK: explicit conversion
14. 대상 변수의 저장소 크기가 같거나 더 클 경우에는 다음과 같은 문을 사용할 수 있습니다.
sbyte x = 10, y = 20; int m = x + y; long n = x + y;
15. 또한 부동 소수점 형식에서 sbyte로의 암시적 변환은 없습니다.
16. 예를 들어, 다음 문에서 명시적 캐스트를 사용하지 않으면 컴파일 오류가 발생합니다.
sbyte x = 3.0; // Error: no implicit conversion from double sbyte y = (sbyte)3.0; // OK: explicit conversion
17. 부동 소수점 형식 및 정수 게열 형식이 함께 사용되는 산술식(arithmetic expressions)에 대한 자세한 내용은 float 및 double을 참조하십시오.
18. 암시적 숫자 변환 규칙에 대한 자세한 내용은 암시적 숫자 변환 표를 참조하십시오.
sealed
1. 클래스에 적용될 경우 sealed 한정자는 다른 클래스가 해당 클래스에서 상속하지 않도록 합니다.
2. 다음 예제에서 B 클래스는 A 클래스에서 상속하지만 B 클래스에서 상속할 수 있는 클래스는 없습니다.
class A {} sealed class B : A {}
3. 기본 클래스의 가상 메서드나 속성을 재정의하는 메서드 또는 속성에 sealed 한정자를 사용할 수도 있습니다.
4. 이렇게 하면 클래스에서 클래스를 파생시키고, 해당 클래스에서 특정 가상 메서드나 속성을 재정의하지 못하도록 할 수 있습니다.
5. 다음 예제에서 Z는 Y에서 상속하지만 Z는 X에 선언되고 Y에 봉인된(sealed) 가상 함수 F를 재정의할 수 없습니다.
class X { protected virtual void F() { Console.WriteLine("X.F"); } protected virtual void F2() { Console.WriteLine("X.F2"); } } class Y : X { sealed protected override void F() { Console.WriteLine("Y.F"); } protected override void F2() { Console.WriteLine("Y.F2"); } } class Z : Y { // Attempting to override F causes compiler error CS0239. // protected override void F() { Console.WriteLine("C.F"); } // Overriding F2 is allowed. protected override void F2() { Console.WriteLine("Z.F2"); } }
6. 클래스의 새 메서드 또는 속성을 정의할 때 virtual로 선언하지 않으면 파생 클래스(deriving classes)가 재정의되지 않도록 할 수 있습니다.
7. 추상 클래스는 추상 메서드 또는 속성의 구현을 제공하는 클래스에서 상속해야 하므로 봉인 클래스와 함께 abstract 한정자를 사용하면 오류가 발생합니다
8. 메서드나 속성에 sealed 한정자를 적용하는 경우 항상 override를 함께 사용해야 합니다.
9. 구조체는 암시적으로 봉인되므로 상속할 수 없습니다.
10. 자세한 내용은 상속을 참조하십시오.
11. 추가 예제는 추상 및 봉인 클래스와 클래스 멤버를 참조하십시오.
sealed class SealedClass { public int x; public int y; } class SealedTest2 { static void Main() { SealedClass sc = new SealedClass(); sc.x = 110; sc.y = 150; Console.WriteLine("x = {0}, y = {1}", sc.x, sc.y); } } // Output: x = 110, y = 150
12. 위 예제에서 다음 문을 사용하여 봉인 클래스에서 상속할 경우
class MyDerivedC: SealedClass {} // Error
13. 다음 오류 메시지가 나타납니다.
'MyDerivedC' cannot inherit from sealed class 'SealedClass'.
14. 클래스, 메서드, 속성을 봉인할지 여부를 결정하려면 일반적으로 다음 두 가지 사항을 고려해야 합니다.
1) 파생 클래스가 클래스를 커스터마이즈(customize)해서 얻을 수 있는 잠재적 이점(the potential benefits)
2) 파생 클래스에서 클래스를 수정하여 해당 클래스가 더이상 올바르게(correctly) 또는 예상대로(as expected) 작동(work)하지 않게 될 가능성(the potential)
short
1. short 키워드는 다음 표에 표시된 크기와 범위에 따라 값을 저장하는 정수 계열 데이터 형식을 나타냅니다(denote).
형식 | 범위 | 크기 | .NET Framework 형식 |
---|---|---|---|
short | -32,768 ~ 32,767 | 부호 있는 16비트 정수 |
2. 다음 예제에서와 같이 short 변수를 선언하고 초기화할 수 있습니다.
short x = 32767;
3. 앞의 선언에서 정수 리터럴 32767은 암시적으로 int에서 short로 변환됩니다.
4. 정수 리터럴이 short 저장소 위치에 맞지 않는(fit into) 경우 컴파일 오류가 발생합니다.
5. 오버로드된 메서드를 호출하는 경우 캐스트를 사용해야 합니다.
6. 예를 들어 다음과 같이 short 및 int 매개 변수를 사용하는 오버로드된 메서드가 있습니다.
public static void SampleMethod(int i) {} public static void SampleMethod(short s) {}
7. 이 경우 short 캐스트를 사용하면 올바른 형식(correct type)이 호출되는 것을 보장합니다(guarantee).
SampleMethod(5); // Calling the method with the int parameter SampleMethod((short)5); // Calling the method with the short parameter
8. short에서 int, long, float, double, decimal로의 미리 정의된 암시적 변환이 있습니다.
9. 저장 크기가 더 큰(larger storage size) 비 리터럴 숫자 형식은 암시적으로 short로 변환할 수 없습니다.
10. 정수 계열 형식의 저장 크기에 대해서는 정수 계열 형식 표를 참조하십시오.
11. 예를 들어 다음과 같은 두 개의 short 변수 x 및 y가 있습니다.
short x = 5, y = 12;
12. 이 경우 다음 대입문에서는 컴파일 오류가 발생합니다.
13. 그 이유는 대입 연산자의 오른쪽에 있는 산술식이 기본적으로 int로 계산되기 때문입니다.
short z = x + y; // Error: no conversion from int to short
14. 이 문제를 해결하려면 캐스트를 사용하십시오.
short z = ( short )(x + y); // OK: explicit conversion
15. 대상 변수의 저장소 크기가 같거나 더 클 경우에는 다음과 같은 문을 사용할 수 있습니다.
int m = x + y; long n = x + y;
16. 부동 소수점 형식에서 short로의 암시적 변환은 없습니다.
17. 예를 들어 다음 문에서 명시적 캐스트를 사용하지 않으면 컴파일러 오류가 발생합니다.
short x = 3.0; // Error: no implicit conversion from double short y = (short)3.0; // OK: explicit conversion
18. 부동 소수점 형식 및 정수 계열 형식이 함께 사용되는 산술식에 대한 내용은 double 및 float을 참조하십시오.
19. 암시적 숫자 변환 규칙에 대한 자세한 내용은 암시적 숫자 변환 표를 참조하십시오.
sizeof
1. 관리되지 않는 형식(an unmanaged type)에 대한 바이트 단위의 크기를 가져오는 데(obtain) 사용됩니다.
2. 관리되지 않는 형식에는 다음 표에 나열된 기본 제공 형식뿐 아니라 다음 형식도 포함됩니ㅏㄷ.
1) 열거형 형식(Enum types)
2) 포인터 형식(Pointer types)
3) 참조 형식인 필드나 속성을 포함하지 않는 사용자 정의 구조체
3. 다음 예제에서는 int의 크기를 검색하는 방법을 보여줍니다.
// Constant value 4: int intSize = sizeof(int);
4. C# 버전 2.0부터는 기본 제공 형식에 sizeof를 적용할 때 unsafe 모드를 사용하지 않아도 됩니다
5. sizeof 연산자는 오버로드되지 않습니다.
6. sizeof 연산자가 반환하는 값은 int 형식입니다.
7. 다음 표에서는 특정 기본 제공 형식을 피연산자로 사용하는 sizeof 식 대신 사용되는(is substituted for) 상수 값을 보여줍니다.
식 | 상수 값 |
---|---|
sizeof(sbyte) | 1 |
sizeof(byte) | 1 |
sizeof(short) | 2 |
sizeof(ushort) | 2 |
sizeof(int) | 4 |
sizeof(uint) | 4 |
sizeof(long) | 8 |
sizeof(ulong) | 8 |
sizeof(char) | 2(유니코드) |
sizeof(float) | 4 |
sizeof(double) | 8 |
sizeof(decimal) | 16 |
sizeof(bool) | 1 |
8. 구조체를 포함한 다른 모든 형식의 경우에는 안전하지 않은 코드 블록(unsafe code blocks)에서만 sizeof 연산자를 사용할 수 있습니다.
9. Marshal.SizeOf 메서드를 사용할 수 있지만 이 메서드가 반환하는 값이 sizeof가 반환하는 값과 항상 같지는 않습니다.
10. Marshal.SizeOf는 형식이 마샬링된 후의 크기를 반환하지만 sizeof는 패딩을 포함하여 공용 언어 런타임(CLR)에서 할당된 크기를 반환합니다.
class MainClass { // unsafe not required for primitive types static void Main() { Console.WriteLine("The size of short is {0}.", sizeof(short)); Console.WriteLine("The size of int is {0}.", sizeof(int)); Console.WriteLine("The size of long is {0}.", sizeof(long)); } } /* Output: The size of short is 2. The size of int is 4. The size of long is 8. */
stackalloc
1. stackalloc 키워드는 안전하지 않은 코드 컨텍스트에서 스택에 메모리 블록을 할당하는 데 사용됩니다.
int* block = stackalloc int[100];
2. 키워드는 지역 변수 이니셜라이저에서만 유효합니다.
3. 다음 코드는 컴파일러 오류를 발생시킵니다.
int* block; // The following assignment statement causes compiler errors. You // can use stackalloc only when declaring and initializing a local // variable. block = stackalloc int[100];
4. 포인터 형식이 관련되기(involved) 때문에 stackalloc에는 unsafe 컨텍스트가 필요합니다.
5. 자세한 내용은 안전하지 않은 코드 및 포인터를 참조하십시오.
6. stackalloc는 C 런타임 라이브러리의 _alloca와 비슷합니다.
7. 다음 예제는 피보나치 수열(the Fibonacci sequence)의 20번째 숫자까지 계산 및 표시합니다.
8. 각 번호에는 이전 두 숫자의 합계입니다.
9. 이 코드에서 int 형식의 요소 100개를 포함하는 데 충분한 크기의 메모리 블록은 힙이 아니라 스택에 할당됩니다.
10. 블록의 주소는 포인터 fib에 저장됩니다.
11. 이 메모리는 가비지 수집의 영향을 받지 않으므로(is not subject to) fixed를 사용하여 고정(pin)하지 않아도 됩니다.
12. 메모리 블록의 수명(lifetime)은 해당 메모리 블록이 정의된 메서드의 수명에 따라 제한됩니다.
13. 즉, 메서드가 반환하기 전에는 메모리를 해제(free)할 수 없습니다.
class Test { static unsafe void Main() { const int arraySize = 20; int* fib = stackalloc int[arraySize]; int* p = fib; // The sequence begins with 1, 1. *p++ = *p++ = 1; for (int i = 2; i < arraySize; ++i, ++p) { // Sum the previous two numbers. *p = p[-1] + p[-2]; } for (int i = 0; i < arraySize; ++i) { Console.WriteLine(fib[i]); } // Keep the console window open in debug mode. System.Console.WriteLine("Press any key to exit."); System.Console.ReadKey(); } } /* Output 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 */
14. 안전하지 않은 코드는 안전한 코드보다 위험합니다.
15. 그러나 stackalloc을 사용하면 CLR(공용 언어 런타임)에서 버퍼 오버런 감지 기능(buffer overrun detection features)이 자동으로 활성화됩니다.
16. 버퍼 오버런을 감지(detect)하면 프로세스가 가능한 한 신속하게 종료되어 악의적인 코드(malicious code)가 실행될 가능성을 최소화(minimize the chance)합니다.
static
1. static 한정자는 특정 개체가 아니라 해당 형식 자체에 속하는 정적 멤버를 선언하는 데 사용됩니다.
2. static 한정자는 클래스, 필드, 메서드, 속성, 연산자, 이벤트 및 생성자와 함께 사용할 수 있지만 클래스 이외의 형식(types other than classes), 소멸자(destructors) 또는 인덱서와는 함께 사용할 수 없습니다.
3. 자세한 내용은 정적 클래스 및 정적 클래스 멤버를 참조하십시오.
4. 다음 클래스는 static으로 선언되며 static 메서드만 포함됩니다.
static class CompanyEmployee { public static void DoSomething() { /*...*/ } public static void DoSomethingElse() { /*...*/ } }
6. 상수 또는 형식 선언은 암시적으로 정적 멤버입니다.
7. 정적 멤버는 인스턴스를 통해 참조할 수 없습니다
8. 대신 형식 이름(the type name)을 통해 참조됩니다.
9. 예를 들어 다음 클래스를 확인해 보십시오.
public class MyBaseC { public struct MyStruct { public static int x = 100; } }
10. 정적 멤버 x를 참조하려면 동일한 범위에서 멤버에 액세스 가능하지 않은 정규화된 이름(the fully qualified name) MyBaseC.MyStruct.x을 사용합니다.
Console.WriteLine(MyBaseC.MyStruct.x);
11. 클래스의 인스턴스에는 해당 클래스의 모든 인스턴스 필드에 대한 별도의 복사본이 포함되지만 각 정적 필드의 복사본은 한 개만 있습니다.
12. this를 사용하여 정적 메서드 또는 속성 접근자(property accessors)를 참조할 수 없습니다.
13. 클래스에 static 키워드가 적용되면 해당 클래스의 모든 멤버가 정적 멤버여야 합니다.
14. 클래스와 정적 클래스는 정적 생성자를 가질 수 있습니다.
15. 정적 생성자(static constructors)는 프로그램이 시작된 후 클래스가 인스턴스되기 전에 호출됩니다.
참고 |
---|
static 키워드는 C++에서보다 더 제한적으로 사용됩니다. C++ 키워드와 비교하려면 Static (C++)을 참조하십시오. |
16. 정적 멤버를 설명하기 위해 회사의 직원을 나타내는 클래스가 있다고 가정합니다.
17. 또한 이 클래스에 직원 수를 계산하는 메서드와 직원 수를 저장하기 위한 필드가 포함되어 있다고 가정합니다(assume)
18. 이 메서드와 필드는 모두 어떤 인스턴스 직원에도 속해 있지 않습니다.
19. 대신 회사 클래스에 속해 있습니다.
20. 따라서 이 메서드 및 필드는 해당 클래스의 정적 멤버로 선언되어야 합니다.
21. 이 예제에서는 새 직원의 이름 및 ID를 읽고 직원 카운터를 1씩 증가시키고 새로운 직원 수와 새 직원에 대한 정보를 표시합니다.
22. 간단하게 설명하기 위해(For simplicity) 이 프로그램은 키보드를 통해 직원의 현재 수를 읽어 들입니다.
23. 실제 응용 프로그램에서는(In a real application) 이 정보를 파일에서 읽어 드립니다.
public class Employee4 { public string id; public string name; public Employee4() { } public Employee4(string name, string id) { this.name = name; this.id = id; } public static int employeeCounter; public static int AddEmployee() { return ++employeeCounter; } } class MainClass : Employee4 { static void Main() { Console.Write("Enter the employee's name: "); string name = Console.ReadLine(); Console.Write("Enter the employee's ID: "); string id = Console.ReadLine(); // Create and configure the employee object: Employee4 e = new Employee4(name, id); Console.Write("Enter the current number of employees: "); string n = Console.ReadLine(); Employee4.employeeCounter = Int32.Parse(n); Employee4.AddEmployee(); // Display the new information: Console.WriteLine("Name: {0}", e.name); Console.WriteLine("ID: {0}", e.id); Console.WriteLine("New Number of Employees: {0}", Employee4.employeeCounter); } } /* Input: Matthias Berndt AF643G 15 * Sample Output: Enter the employee's name: Matthias Berndt Enter the employee's ID: AF643G Enter the current number of employees: 15 Name: Matthias Berndt ID: AF643G New Number of Employees: 16 */
24. 이 예제에서는 아직 선언되지 않은 다른 정적 필드를 사용하여 정적 필드를 초기화할 수 있지만 그 결과는 정적 필드에 명시적으로 값을 할당하기 전까지 정의되지 않은 상태임을 보여 줍니다.
string
1. string 형식은 0개 이상의 유니코드 문자 시퀀스를 나타냅니다.
2. string은 .NET Framework의 String에 대한 별칭입니다.
3. string은 참조 형식이지만 같음 연산자(== 및 !=)(the equality operators)는 참조가 아니라 string 개체의 값을 비교하도록 정의되어 있으므로 좀 더 쉽게 문자열을 비교할 수 있습니다.
string a = "hello"; string b = "h"; // Append to contents of 'b' b += "ello"; Console.WriteLine(a == b); Console.WriteLine((object)a == (object)b);
4. 이 코드는 "True"를 표시한 다음 "False"를 표시하는데, 이는 문자열의 내용이 동일(equivalent)하지만 a와 b는 동일한 문자열 인스턴스를 가리키지 않기 때문입니다.
5. + 연산자는 문자열을 연결합니다(concatenate).
string a = "good " + "morning";
6. 문자열은 변경할 수 없습니다(immutable).
7. 즉, 구문을 보면 문자열 개체를 만든 후 이 개체의 내용을 변경할 수 있는 것처럼 보이지만 이는 가능하지 않습니다.
8. 예를 들어, 다음 코드를 작성하면 컴파일러에서는 새 문자 시퀀스가 있는 새 문자열 개체를 만들어 새 개체에 b가 할당됩니다.
string b = "h"; b += "ello";
9. [] 연산자는 string의 개별 문자에 읽기 전용으로 액세스하는 데 사용할 수 있습니다.
string str = "test"; char x = str[2]; // x = 's';
10. 문자열 리터럴은 string 형식이며 따옴표 붙은 형식과 @-따옴표 붙은 형식의 두 가지 형태로 작성할 수 있습니다.
11. 따옴표 붙은 문자열 리터럴은 다음과 같이 큰따옴표(")(double quotation marks)로 묶습니다(enclosed).
"good morning" // a string literal
12. 문자열 리터럴에는 다음과 같이 이스케이프 시퀀스를 포함한 모든 문자 리터럴이 포함될 수 있습니다.
13. 다음 예제에서는 백슬래시에 이스케이프 시퀀스 \\, 글자 f에 \u0066, 줄 바꿈 \n을 사용합니다.
string a = "\\\u0066\n"; Console.WriteLine(a);
참고 |
---|
이스케이프 코드 \udddd는 유니코드 문자 U+dddd를 나타냅니다. 여기서 dddd는 네 자리 숫자입니다. \Udddddddd와 같은 8자리 유니코드 이스케이프 코드도 사용할 수 있습니다. |
14. 약어 문자열 리터럴(verbatim string literals)은 @로 시작하며 큰따옴표로 묶습니다.
@"good morning" // a string literal
15. 약어 문자열의 이점(the advantage)은 이스케이프 시퀀스를 처리하지 않기 때문에 다음과 같이 정규화된 파일 이름 등을 쉽게 작성할 수 있다는 것입니다.
@"c:\Docs\Source\a.txt" // rather than "c:\\Docs\\Source\\a.txt"
16. @-따옴표 붙은 문자열에 큰따옴표를 포함시키려면 다음과 같이 큰따옴표를 두 번 입력합니다(double it).
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
17. 또한 @ 기호는 C# 키워드인 참조된 식별자(/reference)를 사용하는 데 유용합니다.
18. C# 문자열에 대한 자세한 내용은 문자열을 참조하십시오.
class SimpleStringTest { static void Main() { string a = "\u0068ello "; string b = "world"; Console.WriteLine( a + b ); Console.WriteLine( a + b == "Hello World" ); // == performs a case-sensitive comparison } } /* Output: hello world False */
struct
1. struct 형식은 인벤토리 항목 특성(the characteristics of an item))이나 사각형의 좌표(the coordinates of a rectangle)와 같은 관련 변수의 소규모 그룹을 캡슐화(encapsulate)하는 데 일반적으로 사용되는 값 형식입니다.
2. 다음 예제에서는 간단한 구조체 선언을 보여줍니다.
public struct Book { public decimal price; public string title; public string author; }
3. 구조체는 생성자, 상수, 필드, 메서드, 속성, 인덱서, 연산자, 이벤트 및 중첩 형식도 포함할 수 있습니다.
4. 그러나 이러한 멤버가 여러 개 필요한 경우에는 구조체 대신 클래스 형식을 지정하는 것이 좋습니다.
5. 예제를 보려면 구조체 사용을 참조하십시오.
6. 구조체는 인터페이스를 구현할 수는 있지만 다른 구조체를 상속할 수는 없습니다.
7. 그러므로 구조체 멤버를 protected로 선언할 수는 없습니다.
8. 자세한 내용은 구조체를 참조하십시오.
switch
1. case 참조
'프로그래밍 > C#' 카테고리의 다른 글
C# 컨텍스트 키워드 (0) | 2016.06.06 |
---|---|
C# 키워드 T~Z (0) | 2016.06.03 |
C# 키워드 F~N (0) | 2016.05.21 |
C# 키워드 A-E (0) | 2016.05.13 |
연산자 2 (0) | 2016.05.10 |