C#(한국어: 시 샤프 또는 C 샵)는 마이크로소프트에서 개발한 객체 지향 프로그래밍 언어로, 닷넷 프레임워크의 한 부분으로 만들어졌으며 나중에 ECMA (ECMA-334)와 ISO (ISO/IEC/23270)의 표준으로 자리잡았다. C++와 자바의 문법과 비슷한 문법을 가지고 있다.
패러다임 | 프로그래밍 패러다임: 구조적 프로그래밍, 명령형 프로그래밍, 객체 지향 프로그래밍, 사건 기반 프로그래밍, 비동기 메서드 호출, 함수형 프로그래밍, 제네릭 프로그래밍, 반영, 병행 컴퓨팅 |
---|---|
설계자 | 마이크로소프트 |
개발자 | 마이크로소프트 |
발표일 | 2000년 |
최근 버전 | 12.0 |
최근 버전 출시일 | 2023년 11월 14일 |
플랫폼 | 공통 언어 기반(CLI) |
라이선스 | CLR: MIT 라이선스 모노 컴파일러: GPLv3&MIT 라이선스 라이브러리: LGPLv2 |
파일 확장자 | .cs |
웹사이트 | docs |
주요 구현체 | |
비주얼 C 샤프, 닷넷 프레임워크, 모노, 던GNU | |
Cω, 스페이스 샤프, 폴리포닉 C 샤프, 엔터헤드 C# | |
영향을 받은 언어 | |
C++, 에펠, 자바, 모델-3, 오브젝트 파스칼, ML, VB, 아이콘, 하스켈, 러스트, J#, Cω, F# | |
영향을 준 언어 | |
체펠, D, J#, 해키, 자바, 코틀린, 몽키 X, 네메레, 옥시즌, 러스트, 스위프트, 발라 |
using System; //System이라는 모듈을 사용한다. 해당 모듈은 Console에 관한것들을 담고있다 namespace HelloWorld { //namespace를 정의한다. 자바로 치면 패키지나 프로젝트라고 생각하면 된다 class Program { //클래스를 시작한다. 자바의 클래스와 같다고 생각하면 된다. private static void Main() { //private이라는 구문으로 클래스 내부에서만 가능하게 만든다. static void Main()이라는 구문으로 메인 메소드를 만든다. 이것은 Java 와 다르고 C 와 C++처럼 (string[] args) 가 붙지 않으며 보통 빈칸이다. Console.WriteLine("Hello, World!"); //콘솔에 하얀색 글씨로 Hello World 라고 출력한다. Console.ReadLine(); //그냥 WriteLine 이라고 쓰면 바로 프로그램이 종료된다. ReadLine으로 아무키나 눌러야 종료되도록 한다. } //메인메소드의 끝. 메소드의 끝이라고 할 수 있다. } //클래스의 끝. 클래스밑에 다른 클래스를 만들수 없다 } //네임스페이스의 끝. 폴더의 끝이라고 생각하면 된다
System.Console.WriteLine("Hello, World!"); //System 구문으로 System 을 사용한다는 정의와 동시에 namespace 없이 작동시킨다 //Console 구문으로 콘솔을 출력한다 //WriteLine으로 하얀색 글을 콘솔에 붙인다.
C#은 마이크로소프트 닷넷 프로그램이 동작하는 닷넷 플랫폼을 가장 직접적으로 반영하고, 또한 닷넷 플랫폼에 강하게 의존하는 프로그래밍 언어이다. C#은 그 문법적인 특성이 자바와 상당히 유사하며 C#을 통하여 다룰 수 있는 닷넷 플랫폼의 기술들조차도 자바를 염두에 둔 것이 많아서 자바와 가장 많이 비교되고 있다. 하지만 C#은 자바와 달리 불안전 코드(unsafe code)와 같은 기술을 통하여 플랫폼 간 상호 운용성에 상당히 많은 노력을 기울이고 있다. C#의 기본 자료형은 닷넷의 객체 모델을 따르고 있고, 런타임 차원에서 쓰레기 수집(garbage collection)이 되며 또한 클래스, 인터페이스, 위임, 예외와 같이 객체 지향 언어로서 가져야 할 모든 요소들이 포함되어 있다.
닷넷 프레임워크를 개발하던 시절 클래스 라이브러리는 SMC(Simple Managed C)라 불리는 관리 코드(managed code)를 사용했었다. 1999년 1월, 아네르스 하일스베르가 이끄는 팀이 새로운 언어인 Cool(C-like Object Oriented Language)을 개발했다. 마이크로소프트는 언어의 최종 이름을 Cool로 유지할지도 고려해봤지만 상표 문제로 인해 이뤄지지 않았다. 2000년 7월 PDC에서 닷넷 프로젝트가 발표될 때 즈음 Cool의 이름은 C#으로 정해졌고 클래스 라이브러리와 ASP.NET 런타임은 C#으로 옮겨갔다.
C#은 ISO 소위원회 JTC 1/SC 22에 ISO/IEC 23270:2003으로 제출되었으나 철회 후 ISO/IEC 23270:2006으로 등록되었다.
C#이라는 이름은 음표를 연주할 때 반음 올리는 것을 표시하는 올림표에서 따왔다. C++에서 "++"가 변수의 값을 1 증가시키는 것을 의미하는 것과 비슷하다. 마찬가지로 올림표는 네 개의 "+" 기호와 비슷하므로 C++를 한번 더 증가시켰다는 뜻도 지닌다.
기본 글꼴이나 브라우저의 기술적인 한계와 더불어 키보드에는 올림표 기호(U+266F ♯ )가 포함되지 않기에 문서에서는 대체 기호로 해시 기호(U+0023 # )를 사용하며, ECMA-334 C# 언어 사양 에서도 확인할 수 있다. 그러나 광고나 패키지 포장 등 가능한 경우, 마이크로소프트에서는 의도한 대로 올림표를 사용한다.
버전 | 언어 사양 | 날짜 | 닷넷 프레임워크 | 비주얼 스튜디오 | ||
---|---|---|---|---|---|---|
ECMA | ISO/IEC | 마이크로소프트 | ||||
C# 1.0 | 2002년 12월 | 2003년 4월 | 2002년 1월 | 2002년 1월 | .NET Framework 1.0 | 비주얼 스튜디오 .NET 2002 |
C# 1.2 | 2003년 10월 | 2003년 4월 | .NET Framework 1.1 | 비주얼 스튜디오 .NET 2002 | ||
C# 2.0 | 2006년 6월 | 2006년 9월 | 2005년 9월 | 2005년 11월 | .NET Framework 2.0 | 비주얼 스튜디오 2005 |
C# 3.0 | 없음 | 2007년 8월 | 2007년 11월 | .NET Framework 2.0 (LINQ/쿼리 확장 제외) | 비주얼 스튜디오 2008 | |
C# 4.0 | 2010년 4월 | 2010년 4월 | .NET Framework 4.0 | 비주얼 스튜디오 2010 | ||
C# 5.0 | 2017년 12월 | 2018년 12월 | 2013년 6월 | 2012년 8월 | .NET Framework 4.5 | 비주얼 스튜디오 2012 |
C# 6.0 | 없음 | 없음 | 2015년 7월 | .NET Framework 4.6 | 비주얼 스튜디오 2015 | |
C# 7.0 | 2017년 5월 | .NET Framework 4.7 | 비주얼 스튜디오 2017 |
C#의 기본 문법은 C, C++, 자바 등 C 스타일 언어와 유사하다.
C++ 언어와 비교할 때 C#은 다음과 같은 점에서 단순화되거나 확장되었다.
bool
은 오직 true
와 false
의 논리값만을 가질 수 있으며,상수 또는 정수형 변수에서 암시적으로 변환이 불가능하다. 직접 대입을 위해서는 변환 명령을 이용해야 한다. 반면 C++의 bool
은 정수값을 대입할 수 있다. 또한 C#에서는 if
나 while
문 등의 비교문에서 이용하는 값도 bool
형태로 제한되는 반면, C++에서는 상수 또는 변수를 이용하여 '0이 아닌 값' 또는 '0'의 여부로 비교할 수 있다.static
키워드를 오직 한 번만 초기화를 수행한다는 의미로 이용할 수 없다./unsafe
또는 --unsafe
스위치를 지정하도록 명시해야 한다. unsafe 블록의 사용 예는 다음과 같다.unsafe { int *pA; }
System.IntPtr
이다.(System.UIntPtr
은 특수한 목적으로 쓰이므로 설명에서 제외한다.)
(IntPtr.ToPointer
메서드로 void*
형식을 가져올 수 있음)도 지원한다.
C++에서 포인터는 특정한 형식의 인스턴스 또는 주소값을 가리키기 위한 목적으로 할당되는 주소값을 기억하기 위한 변수로 취급되지만 C#의 포인터는 System.IntPtr
이라는 하나의 완성된 형식에 대한 확장 사양일 뿐이다. 그래서 C++의 포인터와 같은 쓰임새를 C#으로 이식할 수 없는 경우가 상당히 많다.
void*
포인터가 가리키는 값을 얻어낼 수 없고 void*
포인터에 대한 산술 연산도 수행할 수 없다./checked+
로 지정된 경우모든 코드 범위에서 엄격한 산술 연산 검사를 할 수 있으며 /checked-
로 지정된 경우 모든 코드 범위에서 산술 연산 검사를 하지 않도록 할 수 있다. 컴파일러 옵션과는 관계없이 unchecked 블록 안에서는 검사되지 않으며, 반대로 checked 블록 안에서는 검사가 이루어진다.
int a = 0; unchecked { a = int.MaxValue + 20; } checked { a = int.MaxValue * 2; }
using System; namespace FooBar { class Program { private int Test = 123; static void Main(string[] args) { unsafe { Program p = new Program(); fixed (int* ptrX = &p.Test) { Console.Out.Write(Convert.ToString(*ptrX)); *ptrX = 21; Console.Out.WriteLine(Convert.ToString(*ptrX)); } } } } }
IDisposable
인터페이스를 특정 클래스에서 구현하게 된다. IDisposable
인터페이스를 구현하는 클래스는 C#의 using 구문을 이용하여 자동으로 IDisposable.Dispose
메서드를 호출할 수도 있다.System.Object
클래스가 모든 클래스의 선조 클래스이기 때문에 이러한 관대함이 가능하게 되었다. (단, unsafe 블록 내에서 사용되는 포인터 형식의 경우는 예외로 한다.)int*, void*, byte*
, ...와 같이 하나의 완성된 형식으로서 이해할 수 있지만 C++은 메모리 주소값을 저장하도록 되어있는 형태이다. 포인터를 사용하고자 하는 목적은 같지만 C++에서처럼 어떤 곳에서나 주소를 참조할 수 있는 것은 아니므로 정확한 이해가 필요하다. (다만, 특수한 GCHandle
형식을 활용하여 Pinned Object를 생성하는 경우에는 이러한 접근이 가능할 수 있으나 특성에 맞지도 않으며 심각한 성능 저하를 일으키므로 좋은 방법이라고 할 수 없을것이다.)// C# int[] a = new int[5]; int* pA, pB;// C++ int a[5]; int *pA, *pB;
get_foo()
메서드와 set_foo()
메서드로 구분되어 표현되곤 한다.public string Name { get { return m_name; } set { m_name = "Name :: "+value; } } public void MethodOne(string name) { this.Name = "DotNet"; }
C#에서 리플렉션으로 확장하여 사용하는 것이 가능하다. 리플렉션은 자바 언어의 리플렉션과 같은 개념이다.
즉, C/C++에서 사용되던 #include나 #pragma와 같은 지시자를 C#에서는 사용할 수 없으며, C/C++에서 매크로 상수나 매크로 함수 등을 위해 사용되던 #define이 C#에서는 매우 제한적인 용도로 사용된다. 또한 C/C++에는 없던 #region, #endregion 지시자가 새로 추가되었다. 예를 들면 다음과 같다.
#define CsDebug #region 아래는 FooClass 선언입니다. public class FooClass { private int integer; #if CsDebug private string debugmsg; #endif public string DebugMsg { get { #if CsDebug return this.debugmsg; #else return null; #endif } set { #if CsDebug this.debugmsg = value.Clone() as string; #endif } } } #endregion
즉, 모든 인스턴스나 메서드는 반드시 특정 클래스의 멤버로 소속되어야 한다.
대신 C# 3.0부터 이와 비슷한 확장 메서드를 지원하고 있다. 확장 메서드는 정적 클래스의 멤버로 있어야 하며 이 때에도 대상 클래스의 private 멤버에는 접근 할 수 없다.
public class Foo { [MarshalAs(UnmanagedType.U4)] private uint dwValue; [MarshalAs(UnmanagedType.LPWstr)] private string lpcwValue; public uint DWValue { get { return this.dwValue; } set { this.dwValue = value; } } public string LPCWValue { get { return this.lpcwValue; } set { this.lpcwValue = value.Clone() as string; } } } public static class Bar { public static string FooString(this Foo foo) { return string.Format("정수 값은 {0}, 문자열 값은 {1}입니다.", foo.DWValue, foo.LPCWValue); } }
(이 부분은 C++11에서 auto 키워드로 지원한다. )
아래 예제는 정수형으로 이루어진 배열에서 100을 초과하는 값만을 추출하는 코드이다.
public List<int> linqtest(List<int> list) { var result = from k in list where k > 100 select k; return result; }
public static void Print(int a, int b, Func<int> func) { Console.WriteLine("{0} 더하기 {1}은 {2}입니다.", a, b, func(a, b)); } public static void Main() { Print(a, b, f => {Console.WriteLine("func가 호출되었습니다."); return a+b;}); }
This article uses material from the Wikipedia 한국어 article C 샤프, which is released under the Creative Commons Attribution-ShareAlike 3.0 license ("CC BY-SA 3.0"); additional terms may apply (view authors). 별도로 명시하지 않은 경우, 내용은 CC BY-SA 4.0에 따라 사용할 수 있습니다. Images, videos and audio are available under their respective licenses.
®Wikipedia is a registered trademark of the Wiki Foundation, Inc. Wiki 한국어 (DUHOCTRUNGQUOC.VN) is an independent company and has no affiliation with Wiki Foundation.