Tag Archives: C#

C# 6.0 완벽 가이드/ .NET Framework 개요

  • .NET Framework의 거의 모든 능력은 다종다양한 ‘관리되는 형식(managed type)’들을 통해 제공된다. 이 형식들은 계통구조(hierarchy) 형태의 이름공간들로 조직화되어 있으며, 일단의 어셈블리 파일들로 배포, 설치된다. 이들과 CLR(공용 언어 런타임)을 합친 것이 바로 .NET 플랫폼이다.
  • .NET Framework의 형식들 일부는 CLR이 직접 사용한다. 이들은 관리되는 호스팅 환경에 필수적인 형식들로, mscorlib.dll 이라는 어셈블리 안에 들어 있다.
    • C#의 내장 형식들과 기본 컬렉션 클래스들, 그리고 스트림 처리나 직렬화, 반영(reflection), 스레드 적용, 네이티브 상호운용성을 위한 형식들이 여기에 속한다.
  • 이보다 한 수준 위에는 CLR 수준의 기능성에 살을 붙이는 추가적인 형식들이 있다. 이들은 이를테면 XML 처리나 네트워킹, LINQ 같은 기능을 제공한다.
  • .NET Framework의 그 나머지 부분은 응용 API 들로 구성되어 있는데, 이들 대부분은 크게 다음과 같은 3가지 기능 영역으로 분류된다.
    • 사용자 인터페이스 기술
    • 뒷단(backend) 기술
    • 분산 시스템 기술
  • .NET Framework 4.6의 새로운 기능
    • 쓰레기 수거기가 수거를 실행하는 시점을 좀 더 세밀하게 제어할 수 있는 새 메서드들이 GC 클래스에 추가되었다.
    • 새롭고 더 빠른 64비트 JIT 컴파일러가 도입되었다.
    • System.Numerics 이름공간에 하드웨어 가속 행렬 및 벡터 형식들이 추가되었다.
    • 라이브러리 작성자를 위해 System.AppContext라는 새로운 클래스가 추가되었다. 이를 이용해 라이브러리를 작성하면 라이브러리 사용자가 새로운 API 기능들을 선택적으로 전환할 수 있다.
    • Task 인스턴스 생성시 현재 스레드의 문화 설정과 UI 문화 설정이 반영된다.
    • 더 많은 컬렉션 형식들이 IReadOnlyCollection<T>를 구현한다.
    • WPF가 개선되었다. (더 나은 터치 및 고 DPI 처리 등)
    • ASP.NET이 HTTP/2와 Window 10의 TBP(Token Binding Protocol)를 지원한다.
  • .NET Framework 4.5의 새로운 기능
    • Task를 돌려주는 메서드들을 통한 광범위한 비동기성 지원
    • ZIP 압축 프로토콜 지원
    • 새로운 HttpClient 클래스를 통한 HTTP 지원 개선
    • 쓰레기 수거기와 어셈블리 자원 조회 성능 향상
    • WinRT 상호운용성 및 Windows 스토어 모바일 앱 구축을 위한 API 지원
    • 새로운 TypeInfo 클래스 추가
    • 정규 표현식 부합시 만료 시간을 지정하는 능력 추가
    • 병렬 컴퓨팅 부분에서 생산자-소비자 스타일의 네트워크 구축을 위한 Dataflow라는 특화된 라이브러리가 추가

Continue reading

C# 6.0 완벽 가이드/ 고급 C#

대리자

  • 대리자(delegate)는 어떤 메서드를 호출하는 방법을 담은 객체
  • 대리자 형식은 그 형식의 인스턴스, 즉 대리자 인스턴스가 호출할 수 있는 종류의 메서드를 정의한다.
  • 메서드를 대리자 변수에 배정하면 대리자 인스턴스가 생성된다.
  • 대리자 인스턴스는 이름 그대로 호출자의 대리자 역할을 한다. 즉, 호출자가 대리자를 호출하면 대리자가 대상 메서드를 대신 호출해 준다. 이러한 간접 호출에 의해, 호출자와 대상 메서드 사이의 결합(coupling)이 끊어진다.
// 다음과 같은 문장은
Transformer t = Square;

// 다음 문장을 줄여 쓴 것이다.
Transformer t = new Transformer(Square);

// 한편 다음과 같은 표현식은
t(3);

// 다음을 줄여 쓴 것이다.
t.Invoke(3);

Continue reading

C# 6.0 완벽 가이드/ C#의 사용자 정의 형식

클래스

메서드

메서드에 적용할 수 있는 수정자들

정적 수정자 static
접근 수정자 public, internal, private, protected
상속 수정자 new, virtual, abstract, override, sealed
부분 메서드 수정자 partial
비관리 코드 수정자 unsafe, extern
비동기 코드 수정자 async

식 본문 메서드 (C# 6)

int Foo (int x) { return x * 2; }

int Foo (int x) => x * 2; // 위 코드와 동일

void Foo (int x) => Console.WriteLine(x); // 반환형이 void인 함수도 이런 식으로 사용할 수 있다.
  • 위의 코드와 같이 표현식이 본문인 메서드(expression-bodied method)를 줄여서 식본문 메서드라고 부른다. 중괄호와 return 키워드 대신 ‘이중 화살표’가 쓰였다.

Continue reading

C# 6.0 완벽 가이드/ C# 언어의 기초

첫 번째 C# 프로그램

컴파일

  • C# 컴파일러는 확장자가 .cs인 일단의 소스코드 파일들을 컴파일해서 하나의 어셈블리를 생성한다. 어셈블리는 .NET 프로그램 패키징 및 배포 단위이다. 어셈블리는 응용 프로그램(application)일 수도 있고 라이브러리(library)일 수도 있다.
  • 보통의 콘솔 또는 Windows 응용 프로그램은 진입점 Main 메서드를 가지고 있으며 파일 확장자는 .exe이다. 라이브러리의 확장자는 .dll이며, .exe와는 달리 진입점이 없다. 라이브러리의 주된 용도는 라이브러리 안의 코드를 다른 응용 프로그램이나 다른 라이브러리가 호출 또는 참조하는 것이다. .NET Framework는 라이브러리들의 집합이다.
  • C# 컴파일러 프로그램의 이름은 csc.exe이다. C# 프로그램은 Visual Studio 같은 IDE로 컴파일 할 수도 있고, 명령줄에서 csc를 직접 실행해서 컴파일 할 수도 있다.
csc MyFirstProgram.cs // 응용 프로그램 컴파일
csc /target:library MyFirstProgram.cs // 라이브러리 컴파일

구문

키워드와의 충돌 피하기

  • 예약된 키워드에 해당하는 식별자를 꼭 사용해야 한다면 식별자 앞에 접두사 @를 붙이면 된다.
    • @ 기호는 식별자 자체의 일부로 간주되지 않는다. 즉, @myVariable은 myVariable과 같다.
    • 접두사 @는 C#과는 다른 키워드들을 가진 다른 .NET 언어로 작성된 라이브러리를 C# 프로그램에서 사용할 때 유용할 수 있다.

Continue reading

C# 6.0 완벽 가이드/ C#과 .NET Framework 소개

(필요한 부분만 정리)

C#과 CLR의 관계

  • C#은 자동 메모리 관리와 예외 처리 같은 다양한 기능을 갖춘 런타임에 의존한다. C#의 설계는 해당 실행시점 기능들을 제공하는 Microsoft CLR의 설계와 밀접하게 대응된다.(비록 기술적으로는 C#이 CLR과 독립적이지만) 게다가 C#의 형식 체계는 CLR의 형식 체계와 밀접하게 대응된다.

CLR과 .NET Framework

  • .NET Framework는 CLR과 아주 다양한 라이브러리들의 집합으로 구성되어 있다. 그 라이브러리 집합에는 핵심 라이브러리들과 그 핵심 라이브러리들에 의존하는 응용 라이브러리들이 있다.
  • CLR은 관리되는 코드(managed code)를 실행하기 위한 런타임이다. C#은 여러 관리되는 언어(managed language) 중 하나인데, 관리되는 언어로 작성한 소스 코드를 컴파일하면 관리되는 코드가 생성된다. 관리되는 코드를 실행 파일(.exe) 또는 라이브러리(.dll) 형태로 만들고 그것을 형식 정보, 즉 메타자료(metadata)와 함께 하나의 패키지로 묶은 것을 어셈블리(assembly)라고 부른다.
  • 관리되는 코드는 중간 언어(intermediate language, IL)로 표현된다. 어셈블리를 적제(load)할 때 CLR은 어셈블리에 담긴 IL 코드를 해당 컴퓨터(x86 등) 고유의 기계어 코드로 변환한다. 이러한 변환을 담당하는 것이 CLR의 JIT(just-in-time) 컴파일러이다. 어셈블리는 원래의 원본 언어의 구성을 거의 그대로 유지하기 때문에 코드를 조사하기 쉽고 심지어 동적으로 생성하기도 쉽다.
    • ILSpy나 dotPeek, Reflector 같은 도구를 이용하면 IL 어셈블리의 내용을 조사하고 역컴파일 할 수 있다.
  • CLR은 여러 실행시점 서비스들의 호스트 역할을 한다. 그런 서시브들로는 이를테면 메모리 관리, 라이브러리 적재, 보안 서비스 등이 있다. CLR은 언어 중립적이므로 여러 언어(C#, F#, Visual Basic, .NET, Managed C++ 등)로 응용 프로그램을 개발하는 것이 가능하다.

Continue reading

C#/ Exponential Notation

지수 표기법

자리수가 큰 수를 지수를 이용해서 줄여서 표기하는 법을 말한다. 특정 숫자를 Numberx10n 꼴로 만든 후에, 지수인 n을 e 다음에 표기하는 것. 예컨대 12000000000 => 1.2e+9, 0.00000012 => 1.2e-7 같은 식으로 표현된다. 자리수가 큰 숫자를 짧게 줄여 쓰는 표기법.

e 다음에 오는 숫자가 양수면 10n 형태이기 때문에 뒤의 숫자만큼 오른쪽으로 소수점을 옮기고, 음수면 (1/10)n 형태이기 때문에 뒤의 숫자만큼 왼쪽으로 소수점을 옮긴다.

지수 표기법 변환

지수 표기법을 일반 숫자로 바꾸기

지수 표기법으로 넘어온 데이터를 일반 숫자로 바꾸려면 각 숫자 형식의 Parse를 시도하면 된다. 물론 Parse 자체보다는 TryParse가 안전하니 그 방법을 사용하는 것을 권장한다. TryParse는 out 키워드가 포함되어야 한다.

// parse를 이용한 방법
decimal x = decimal.Parse("1.2345E-02", NumberStyles.Any);

// try parse를 이용한 방법
// NumberStyle 뿐만 아니라 CultureInfo도 포함되어야 한다.
decimal result;
if( !decimal.TryParse("1.2345E-02", NumberStyles.Any, CultureInfo.InvariantCulture, out result) )
{
     // 실패시 처리
}

일반 숫자를 지수 표기법으로 바꾸기

일반 숫자를 지수 표기법으로 바꾸는 것은 매우 쉽다. 해당 숫자 형식을 ToString(“e”) 해주면 된다.

decimal num = 10000000000m;
string ex = num.ToString("e");

C#/ Linked List

Linked List의 개념

자료구조에서 배열은 초기화할 때 메모리 크기가 정해지기 때문에 메모리 관리에 뛰어나고 사용도 쉽지만 유연함이 떨어진다. 이에 반해 연결 리스트는 연결이 언제 추가, 삭제될지 모르기 때문에 메모리 상에 이곳저곳에 퍼져있게 되어 메모리 관리의 효율성은 떨어지지만 새로운 연결을 추가하거나 기존 연결을 삭제하는 유연함은 대단히 높다.

연결 리스트는 자기 자신의 데이터 + 다음 노드의 포인터로 구성되는데, 그 포인터를 이용해서 순차적인 리스트를 구성한다.

C#에서의 Linked List

C#에서는 LinkedList<T> 를 통해 연결 리스트를 사용할 수 있다. AddFirst(), AddLast(), AddAfter(), AddBefore() 등 연결 리스트의 기본적인 개념을 이용한 메서드들이 제공되고 있는데, 기본적으로 List<T> 보다 성능이 떨어지므로 List<T>를 사용하는 것을 권장한다.

연결리스트는 개념만 이해하면 좋을 듯.

C#/ Using과 IDisposable

Using과 IDisposable

C# 에서 메모리는 가비지 컬렉터가 관리해 주지만, 그 외의 열린 파일, 스트림 같은 관리되지 않는 리소스들은 인식하지 못한다. 이런 리소스들은 프로그래머가 명시적으로 해제를 해줘야 하는데 그때 사용하는게 Dispose()이다.

가비지 컬렉터가 제어할 수 없는 리소스를 제어하는 클래스가 IDisposable을 상속 받아 Dispose()를 구현하고 using을 통해 사용하면 된다.

public class Book : IDisposable
{
    public void Dispose ()
    {
        // 리소스 해제
    }
}

public class Program
{
    public void ReadBook ()
    {
        using (Book novel = new Book())
        {
            // 실행문
        }
    }
}

위와 같이 코드를 구성하면 using 블록을 빠져나갈 때 프로그램이 Dispose()를 실행시켜줘서 리소스를 자동으로 해제하게 된다. using이 네임스페이스를 지정하는 것 외에 Dispose()를 실행시키는 것으로도 쓰이는 것이다.

C#/ DLL 사용하기

C#에서 만든 DLL 사용하기

C#에서 만들어진 DLL 사용하는 방법은 매우 쉽다. using 키워드로 해당 DLL 을 불러온 후에 일반 클래스 사용하듯이 사용하면 된다.

using MyDLL;

static void Main (string[] args)
{
    // MyDLL에 정의된 클래스로 객체 정의하기
    Calcurate cal = new Calcurate();

    int resultAdd = cal.add(1, 2);
    int resultMinus = cal.minus(5, 3);
    int resultMultiply = cal.multiply(2, 4);
    int resultDivide = cal.divide(6, 3);
}

C, C++에서 만든 DLL 사용하기

C나 C++로 만든 DLL은 System.Runtime.InteropServices을 using 한 후에, DLLImport라는 애트리뷰트와 extern이라는 키워드를 이용해서 사용해야 한다.

using System.Runtime.InteropServices;

public class SqliteDatabase
{
    [DllImport("sqlite3", EntryPoint = "sqlite3_open")]
    private static extern int sqlite3_open (string filename, out IntPtr db);

    ...

    void Open (string path)
    {
        IntPtr _connection;

        if (sqlite3_open (path, out _connection) != 0) 
        {
            throw new SqliteException ("Could not open database file: " + path);
        }
    }
}

extern은 해당 메서드의 구현을 바깥 –여기서는 DLL– 에 맡긴다는 의미다. extern 한정자가 붙은 메서드는 static으로 선언되어야 한다.

extern 키워드가 들어간 함수 이름과 매개변수는 DLL 코드 안에 정의된 것과 같아야 한다. 이렇게 정의된 메서드는 일반 메서드처럼 사용할 수 있다.

C#/ String과 StringBuilder

String과 StringBuilder

string은 char[]로서 immutable 타입이다. 이것이 무슨 말인고 하니 string에 ‘+’ 연산을 하면, 현재 string에 새로운 string에 더해지는게 아니라, 현재 string과 새로운 string을 더한 새로운 string을 만들어 낸다는 이야기다.

아래와 같은 코드는 loop를 돌 때마다 추가적으로 string을 만들어 낸다. string이 char[]임을 생각해보면 사실 당연한 결과다.

string num = "";

for (int i = 0; i < 10; i++)
{
    num += i.ToString();
}

이는 자원 낭비이므로 위와 같이 string을 반복적으로 연산할 일이 있을 때는 StringBuilder를 사용하도록 권장된다. StringBuilder는 string과는 사용법이 약간 다른데, 변수보다는 메서드를 사용하는 방식에 가깝다.

StringBuilder num = new StringBuilder();

for (int i = 0; i < 10; i++)
{
    num.Append(i.ToString());
}

StringBuilder는 ToString() 으로 string 타입으로 변환시킬 수 있다.