C#에는 많은 기본 제공 참조 형식이 있습니다. 이러한 형식에는 .NET 라이브러리의 형식에 대한 동의어인 키워드 또는 연산자가 포함됩니다.
C# 언어 참조는 가장 최근에 릴리스된 C# 언어 버전을 문서화합니다. 또한 예정된 언어 릴리스의 공개 미리 보기 기능에 대한 초기 설명서도 포함되어 있습니다.
설명서는 언어의 마지막 세 버전 또는 현재 공개 미리 보기에서 처음 도입된 기능을 식별합니다.
팁 (조언)
C#에서 기능이 처음 도입된 시기를 찾으려면 C# 언어 버전 기록에 대한 문서를 참조하세요.
개체 유형
object 형식은 .NET에서 System.Object의 별칭입니다. C#의 통합 형식 시스템에서 사용자 정의 및 미리 정의된 참조 형식과 값 형식을 비롯한 모든 형식은 직접 또는 간접적으로 System.Object에서 상속합니다. 형식의 변수에 모든 형식의 값(ref ref struct구조체 참조 제외)을 할당합니다object. 모든 object 변수에 리터럴 null 을 기본값으로 할당할 수 있습니다. 값 형식 변수를 변환하면 object값이 boxed됩니다. 형식의 변수를 값 형식 object 으로 변환하면 값이 unboxed가 됩니다. 자세한 내용은 boxing 및 unboxing을 참조하세요.
문자열 유형
string 형식은 0자 이상의 유니코드 문자 시퀀스를 나타냅니다. .NET에서는 .NET string 의 별칭 System.String입니다.
string 참조 형식이지만 같음 연산 == 자는 != 참조가 아닌 개체의 string 값을 비교합니다. 값 기반 같음은 문자열 같음 테스트를 보다 직관적으로 만듭니다. 예시:
string a = "hello";
string b = "h";
// Append to contents of 'b'.
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));
앞의 예제에서는 문자열의 내용이 동일하지만 a 동일한 문자열 인스턴스를 참조하지 않으므로 "True" 및 b "False"를 표시합니다.
+ 연산자는 문자열을 연결합니다.
string a = "good " + "morning";
앞의 코드는 "good morning"을 포함하는 문자열 개체를 만듭니다.
문자열은 변경할 수 없습니다 . 문자열 개체를 만든 후에는 문자열 개체의 내용을 변경할 수 없습니다. 예를 들어 이 코드를 작성할 때 컴파일러는 실제로 새 문자열 개체를 만들어 새 문자 시퀀스를 저장하고 해당 새 개체를 b할당합니다. 할당된 b 메모리(문자열 "h"가 포함된 경우)는 가비지 수집에 적합합니다.
string b = "h";
b += "ello";
연산자를 사용하여 문자열의 [] 개별 문자에 읽기 전용으로 액세스할 수 있습니다. 유효한 인덱스는 0에서 시작되고 문자열의 길이보다 작아야 합니다.
string str = "test";
char x = str[2]; // x = 's';
비슷한 방식으로 연산자를 사용하여 문자열의 [] 각 문자를 반복할 수 있습니다.
string str = "test";
for (int i = 0; i < str.Length; i++)
{
Console.Write(str[i] + " ");
}
// Output: t e s t
문자열 리터럴
문자열 리터럴은 형식 string 이며 원시, 따옴표, 축자 등 세 가지 형식으로 제공됩니다.
원시 문자열 리터럴은 이 스케이프 시퀀스를 요구하지 않고 임의의 텍스트를 포함합니다. 원시 문자열 리터럴에는 공백과 새 줄, 포함된 따옴표 및 기타 특수 문자가 포함될 수 있습니다. 원시 문자열 리터럴은 최소 세 개의 큰따옴표(""")로 묶입니다.
"""
This is a multi-line
string literal with the second line indented.
"""
세 개 이상의 큰따옴표 문자 시퀀스를 포함할 수도 있습니다. 텍스트에 포함된 따옴표 시퀀스가 필요한 경우 필요에 따라 더 많은 따옴표로 원시 문자열 리터럴을 시작하고 끝냅니다.
"""""
This raw string literal has four """", count them: """" four!
embedded quote characters in a sequence. That's why it starts and ends
with five double quotes.
You could extend this example with as many embedded quotes as needed for your text.
"""""
원시 문자열 리터럴에는 일반적으로 포함된 텍스트와 별도의 줄에 시작 및 끝 따옴표 시퀀스가 있습니다. 여러 줄 원시 문자열 리터럴은 자체 따옴표로 묶인 문자열을 지원합니다.
var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."
시작 및 끝 따옴표가 별도의 줄에 있는 경우 여는 따옴표와 끝 따옴표 앞의 줄 바꿈은 최종 내용에 포함되지 않습니다. 닫는 따옴표 시퀀스는 문자열 리터럴의 맨 왼쪽 열을 나타냅니다. 전체 코드 형식과 일치하도록 원시 문자열 리터럴을 들여쓰기할 수 있습니다.
var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."
// The leftmost whitespace is not part of the raw string literal
끝 따옴표 시퀀스의 오른쪽에 있는 열은 유지됩니다. 이 동작을 사용하면 다음 예제와 같이 JSON, YAML 또는 XML과 같은 데이터 형식에 원시 문자열을 사용할 수 있습니다.
var json= """
{
"prop": 0
}
""";
팁 (조언)
Visual Studio 및 C# Dev Kit는 원시 문자열 리터럴에 JSON 데이터 또는 정규식이 포함될 때 몇 가지 유효성 검사 및 구문 강조 표시를 제공합니다.
도구는 텍스트를 구문 분석합니다. 도구에서 텍스트가 JSON 또는 정규식을 나타낸다는 확신이 있는 경우 편집기에서 구문 색 지정을 제공합니다.
형식을 나타내는 선언 위에 주석을 추가하여 해당 환경을 개선할 수 있습니다.
-
// lang=json는 원시 문자열 리터럴이 JSON 데이터를 나타냅니다. -
// lang=regex는 정규식을 나타내는 원시 문자열 리터럴을 나타냅니다.
원시 문자열 리터럴이 매개 변수가 형식을 나타내는 데 사용하는 System.Diagnostics.CodeAnalysis.StringSyntaxAttribute 인수로 사용되는 경우 이러한 도구는 일부 형식 형식에 대한 원시 문자열 리터럴의 유효성을 검사합니다. JSON 및 regex가 모두 지원됩니다.
일부 형식의 경우 주석 또는 특성을 사용하면 코드 제안이 형식에 따라 문자열 리터럴에 대한 수정 사항을 제공할 수 있습니다.
텍스트 줄이 닫는 따옴표 시퀀스의 왼쪽으로 확장되면 컴파일러가 오류를 반환합니다. 여는 따옴표 시퀀스와 닫는 따옴표 시퀀스는 동일한 줄에 있을 수 있으며 문자열 리터럴은 따옴표 문자로 시작하거나 끝나지 않습니다.
var shortText = """He said "hello!" this morning.""";
원시 문자열 리터럴을 문자열 보간과 결합하여 출력 문자열에 따옴표 문자와 중괄호를 포함할 수 있습니다.
따옴표가 있는 문자열 리터럴은 큰따옴표(")로 묶여 있습니다.
"good morning" // a string literal
문자열 리터럴에는 모든 문자 리터럴이 포함될 수 있습니다. 이스케이프 시퀀스가 포함됩니다. 다음 예제에서는 이스케이프 시퀀스 \\를 백슬래시에 사용하고, \u0066을 f에 사용하고, \n을 줄 바꿈에 사용합니다.
string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
// F
참고 항목
이스케이프 코드 \udddd(여기서 dddd는 4자리 숫자)는 유니코드 문자 U+dddd를 나타냅니다. 8자리 유니코드 이스케이프 코드 \Udddddddd도 인식됩니다.
축자 문자열 리터럴은 @로 시작하며 큰따옴표로 묶여 있습니다. 예시:
@"good morning" // a string literal
축자 문자열의 장점은 이스케이프 시퀀스가 처리 되지 않아 쓰기가 쉽다는 것입니다. 예를 들어 다음 텍스트는 정규화된 Windows 파일 이름과 일치합니다.
@"c:\Docs\Source\a.txt" // rather than "c:\\Docs\\Source\\a.txt"
@-따옴표로 묶인 문자열에 큰따옴표를 포함하려면 다음과 같이 두 배로 지정합니다.
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
UTF-8 문자열 리터럴
.NET은 UTF-16 인코딩을 사용하여 문자열을 저장합니다. UTF-8은 웹 프로토콜 및 기타 중요한 라이브러리의 표준입니다. 문자열 리터럴에 u8 접미사를 추가하여 UTF-8 인코딩을 지정할 수 있습니다. 컴파일러는 UTF-8 리터럴을 개체로 ReadOnlySpan<byte> 저장합니다. UTF-8 문자열 리터럴을 사용하면 다음 코드와 같이 동등한 System.ReadOnlySpan<T> 선언보다 더 명확한 선언이 만들어집니다.
ReadOnlySpan<byte> AuthWithTrailingSpace = new byte[] { 0x41, 0x55, 0x54, 0x48, 0x20 };
ReadOnlySpan<byte> AuthStringLiteral = "AUTH "u8;
UTF-8 문자열 리터럴을 배열 ReadOnlySpan<T>.ToArray() 로 저장하려면 리터럴이 포함된 바이트를 변경 가능한 배열에 복사합니다.
byte[] AuthStringLiteral = "AUTH "u8.ToArray();
UTF-8 문자열 리터럴은 컴파일 시간 상수가 아닙니다. 런타임 상수입니다. 따라서 선택적 매개 변수의 기본값으로 사용할 수 없습니다. UTF-8 문자열 리터럴을 문자열 보간과 결합할 수 없습니다. 동일한 문자열 식에는 $ 토큰과 u8 접미사를 사용할 수 없습니다.
대리자 형식
delegate 형식의 선언은 메서드 시그니처와 유사합니다. 반환 값이 있으며 모든 형식의 매개 변수를 개수에 관계없이 사용할 수 있습니다.
public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);
.NET에서 System.Action 및 System.Func 유형은 많은 일반 대리자에 대한 일반적인 정의를 제공합니다. 새 사용자 지정 대리자 형식을 정의할 필요가 없습니다. 대신 제공된 제네릭 형식의 인스턴스화를 만들 수 있습니다.
A delegate 는 명명된 메서드 또는 익명 메서드를 캡슐화하는 데 사용할 수 있는 기본 제공 참조 형식입니다. 대리자는 C++의 함수 포인터와 비슷하지만 형식 안전성과 보안성을 제공한다는 점이 다릅니다. 대리자 적용에 대해서는 대리자 및 제네릭 대리자를 참조하세요. 대리자는 이벤트의 기반이 됩니다. 대리자를 명명된 메서드 또는 익명 메서드와 연결하여 인스턴스화합니다.
호환되는 반환 형식 및 입력 매개 변수가 있는 메서드 또는 람다 식을 사용하여 대리자를 인스턴스화해야 합니다. 메서드 시그니처에서 허용되는 가변성 수준에 대한 자세한 내용은 대리자의 가변성을 참조하세요. 익명 메서드와 함께 사용하려면 대리자와 함께 연결할 코드를 선언합니다.
런타임에 관련된 대리자 형식이 변형 변환으로 인해 다른 경우 런타임 예외로 인해 대리자 조합 또는 제거가 실패합니다. 다음 예제에서는 실패하는 상황을 보여 줍니다.
Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
// Valid due to implicit reference conversion of
// objectAction to Action<string>, but might fail
// at run time.
Action<string> combination = stringAction + objectAction;
새 대리자 개체를 만들어 올바른 런타임 형식으로 대리자를 만들 수 있습니다. 다음 예제에서는 이 해결 방법을 앞의 예제에 적용할 수 있는 방법을 보여 줍니다.
Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
// Creates a new delegate instance with a runtime type of Action<string>.
Action<string> wrappedObjectAction = new Action<string>(objectAction);
// The two Action<string> delegate instances can now be combined.
Action<string> combination = stringAction + wrappedObjectAction;
비슷한 구문을 사용하는 함수 포인터를 선언할 수 있습니다. 함수 포인터는 대리자 형식을 인스턴스화하고 가상 calli 메서드를 호출하는 대신 Invoke 명령을 사용합니다.
동적 형식
이 형식은 dynamic 변수와 해당 멤버에 대한 참조가 컴파일 시간 형식 검사를 무시한다는 것을 나타냅니다. 대신, 이러한 작업은 런타임에 확인됩니다.
dynamic 형식은 Office Automation API와 같은 COM API, IronPython 라이브러리 등의 동적 API 및 HTML DOM(문서 개체 모델)에 대한 액세스를 간소화합니다.
dynamic 형식은 대부분의 상황에서 object 형식처럼 동작합니다. 특히 null이 아닌 모든 식은 dynamic 형식으로 변환될 수 있습니다. 형식은 dynamic 컴파일러가 형식의 식을 dynamic포함하는 확인 작업을 확인하거나 형식을 검사하지 않는다는 점에서 다릅니다object. 컴파일러는 작업에 대한 정보를 패키지하며, 나중에 해당 정보는 런타임에 작업을 평가하는 데 사용됩니다. 이 과정에서 dynamic 형식의 변수는 object 형식의 변수로 컴파일됩니다. 따라서 dynamic 형식은 컴파일 시간에만 존재하고 런타임에는 존재하지 않습니다.
다음 예제에서는 형식의 변수와 형식 dynamic 의 object변수를 대조합니다. 컴파일 시간에 각 변수의 형식을 확인하려면 dyn 문의 obj 또는 WriteLine 위에 마우스 포인터를 놓습니다. IntelliSense를 사용할 수 있는 편집기로 다음 코드를 복사합니다. IntelliSense는 에 대해 dyn을 표시하고 에 대해 obj를 표시합니다.
class Program
{
static void Main(string[] args)
{
dynamic dyn = 1;
object obj = 1;
// Rest the mouse pointer over dyn and obj to see their
// types at compile time.
System.Console.WriteLine(dyn.GetType());
System.Console.WriteLine(obj.GetType());
}
}
WriteLine 문은 dyn 및 obj의 런타임 형식을 표시합니다. 이 시점에는 둘 다 동일한 형식인 정수입니다. 다음 출력이 생성됩니다.
System.Int32
System.Int32
컴파일 시간에 dyn 및 obj 간의 차이를 보려면 앞의 예제에서 선언과 WriteLine 문 사이에 다음 두 줄을 추가합니다.
dyn = dyn + 3;
obj = obj + 3;
obj + 3 식에 정수와 개체를 추가하려는 시도와 관련해서 컴파일러 오류가 보고됩니다. 하지만 dyn + 3에 대한 오류는 보고되지 않습니다.
dyn(이)가 포함된 식은 dyn의 형식이 dynamic이기 때문에 컴파일 시간에 확인되지 않습니다.
다음 예제에서는 여러 선언에 dynamic을 사용합니다. 또한 Main 메서드는 컴파일 시간 형식 검사를 런타임 형식 검사와 비교합니다.
using System;
namespace DynamicExamples
{
class Program
{
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
Console.WriteLine(ec.ExampleMethod(10));
Console.WriteLine(ec.ExampleMethod("value"));
// The following line causes a compiler error because ExampleMethod
// takes only one argument.
//Console.WriteLine(ec.ExampleMethod(10, 4));
dynamic dynamic_ec = new ExampleClass();
Console.WriteLine(dynamic_ec.ExampleMethod(10));
// Because dynamic_ec is dynamic, the following call to ExampleMethod
// with two arguments does not produce an error at compile time.
// However, it does cause a run-time error.
//Console.WriteLine(dynamic_ec.ExampleMethod(10, 4));
}
}
class ExampleClass
{
static dynamic _field;
dynamic Prop { get; set; }
public dynamic ExampleMethod(dynamic d)
{
dynamic local = "Local variable";
int two = 2;
if (d is int)
{
return local;
}
else
{
return two;
}
}
}
}
// Results:
// Local variable
// 2
// Local variable
C# 언어 사양
자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.
참고 항목
.NET