01 뇌를자극하는c# 자료형

27 분 소요

자료형

CTS(Common Type System)

  • .Net Framework 위에 있는 언어들이 따르고 있는 기본 데이터 형식의 표준.
  • System.Byte, System.int32, System.String 같은 것들이 여기에 속함.

  • object
    • 모든 자료형의 조상으로, string ToString(), Type GetType(), Typecode GetTypeCode() 등을 메소드로 가져 모든 자식들이 오버리이드 해서 씀.
    • 값 형식을 받으면 Boxing(Heap 에 넣음)하고 대입 등에는 Unboxing 함.

값형식, 참조형식

string, object, class 형식은 참조형식, 나머진 다 값형식

  • 참조형식에서는 복사가 안되고, 복사는 IClonable::Clone() 을 상속해서 사용함
  • 헷갈리면 null 로 초기화가 되는지 체크.

특수형태

nullable

  • 값, 참조 관계 없이 자료형 뒤에 ? 붙여서 씀.
  • HasValue, Value 속성을 가짐.
  • 참조형식의 경우 nullable 이면 null 인 경우라도 상관없다는 의미

var

  • 컴파일러가 실제 자료형을 파악해 처리해주는 것.
    • object 랑 다름.
  • 지역변수로만 사용가능

Anomymous Type

  • Property 생성자의 {} 만으로 생성해 사용하는 것.
  • 읽기만 가능하고 LINQ 와 시너지가 좋음
Code
{
    var k = new { a = 10, b = "sadf"};
    Console.WriteLine("{0} {1}", k.a, k.b);
}

기본 자료형

실수형 자료형은 상수로 할당시 접미사가 안맞으면 에러남.

  • float a = 3.14f; double b = 3.14; decimal c = 3.14m;

decimal

  • 16 byte. 대략 -2^28 ~ 2^28
  • floating decimal point type.(float 은 floating binary point type)

char => 2 byte. UTF-16 이 기본. 16 넘으면 여러 char 씀

형변환

값형식의 경우 형식 변환 연산자 를 사용.

  • (int) 같은거
  • 이때 비정상적인 변환의 경우 터지므로 값형식에서만 사용하는 것이 정석임

참조형식의 경우

  • [instanceName] is [ClassName] => 타입확인
  • [instanceName] as [ClassName] => 타입변환
    • 이때 터지지 않고 널처리가 가능하므로 참조형식에서는 이 방식을 써야함.
    • 또한 널 값을 못넣어 당연하게도 값형식에서는 사용 못함.

new 를 이용한 생성에서는 값형식, 참조형식에 상관없이 명시적 타입변환을 해줘야함.

Class

클래스 내부

Parameter

call by reference ref, in, out

variable argument params

  • void AAA(params int[] args) { for(int i =0; i < args.Length; i++);}

named argument

  • AAA(args : new int[]{1, 2, 3, 4});
  • non named argument 가 있는 경우 named argument 는 뒤에 넣어야함.

Property

데이터의 오염엔 메소드처럼 안전하고 다룰 때는 필드처럼 편안함.

C#4.0 에서 Auto-Implemented Property 로 간단히 ; 로 처리됨. 이때 변수는 자동으로 k_[PropertyName] 으로 생성해줌.

Prpoerty 를 이용해서 생성자에서 바로 처리도 가능함. 이때 실행 순서는 생성자 -> Property

Code
public abstract class AAA {
    // int a = 0; => k_a
    public int A
    {
        get;   //get { return a; }
        set;   //set { a = value; }
    }   
}

...
{
	A a = new AAA(){ A = 10, }; // Property Initialize
}

Constructor

this()

  • 생성자에서 c++ 과 비슷하게 : 뒤에 호출하면 파라미터만 다른 생성자를 호출할 수 있음.

Destroyer

소멸자를 지정하면 GC 가 object 로부터 상속받은 Finalize() 메소드를 족보를 타고 올라가며 호출해서 느려질 수도 있음. 또한 CLR 의 GC 가 최적화가 잘 되어있어 소멸자를 만들 이유가 특별한 경우 외엔 없음.

Access Modifier

class 에 대해서 public 을 붙이던지, 하나도 안붙여서 private 이 되던지 둘중하나. namespace 에 대한 접근성을 지정하는 것으로, 같은 namespace 에서는 다 접근 가능함.

method 에 대해서는

  • public, protected, private
  • internal => 같은 Assembly 에 있는 코드(cf. exe, dll) 에서는 public, 외엔 private
  • protected internal => 같은 Assembly 에 있는 코드에서는 protected, 외엔 private
  • sealed => c++ 의 final

상속

상속은 하나, 인터페이스는 여러개.

base 를 통해 바로 접근할 수 있고, 생성자에서 파라미터를 넣을 수 있음.

상속관련 한정자

  • virtual 키워드로 가상함수를 지원함
    • 이때 c++ 과 다르게 이 키워드가 있는 장소에 override 를 반드시 넣음.
    • override 가 없으면 다형성이 적용되지 않음.
    • override 상속의 경우 부모의 access modifier 보다 더 개방적이지 못함. (부모가 protected 이면 자식은 protected 이하만 가능)
  • override 앞에 sealed 를 같이 넣으면 자식에서의 override 를 막음.
  • abstract 은 구현되지 않았다는 걸 빼면 가상함수와 똑같음.
    • override 도 필수임.
  • 이 자리에 new 를 넣으면 부모 메소드만 숨기는 기능. 다형성을 제외하면 override 랑 비슷한 결과.

Indexer

Code
    public class AAA {
        protected int this[Int16 index]
        {
            get { return 10; }
            set {; }
        }
    }


클래스 변형

중첩 클래스

소속된 클래스의 private 멤버에도 접근가능.

분할 클래스

앞에 partial 을 쓰면 여러 곳에서 구현가능해 파일을 나눠서 보기 편하게함.

확장 클래스

Code
public static class Int_Extension
{
    public static int Power(this int a, int b)
    {
        int res = a;
        while (--b > 0) res *= a;
        return res;
    }
}
...
{
	10.Power(4); // 10^4
}

추상 클래스

Code
    public abstract class BB
    {
        protected abstract int A { get; set; }  // abstract or virtual 은 private 안됨
        public abstract void Get(); 
    }
    
    public class BBB : BB
    {
        protected override int A { get; set; }   // property 도 override 해야함
        public override void Get() { }           // 부모보다 더 개방적이게 access modifiy 변경 안됨
    }


abstract 가 앞에 붙음.

  • 인스턴스를 만들 수 없고
  • Abstract Method 를 메소드 앞에 abstract 를 붙여 가능함
  • Abstract Property 를 프로퍼티 앞에 abstract 를 붙여 가능함. 내용은 자동 구현 프로퍼티처럼 넣으면 됨.

Interface

Code
    public interface ICCC
    {
        public int V { get; }               // Interface Property 는 파생클래스에서 꼭 구현해야함. 
        public abstract void Print(int a);  // abstract 있으나 없으나 override, public/private 못쓰니 똑같음
        public void Print2();
    }
    
    public class C : ICCC
    {
        public int V { get; set; }
        void ICCC.Print(int a) { }   // public 못넣음
        public void Print2(int a) {} // public 넣어야함.
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            C b = new C();
            b.V = 10;
            (b as ICCC).Print(10); // 명시적 형변환
            b.Print2();
        }
    }


Method, Event, Property, Indexer 만 가질 수 있고 구현부는 가질 수 없음.

  • 모든 멤버에 대해서 Access Modifier 를 사용할 수 없고 기본이 public 임. Derivated Class 는 모든 Method 및 Property 를 public 으로 자동으로 수식되며 다른 Modifier 는 사용할 수 없음.
  • Method 는 다중상속의 모호성을 피하기위해 [InterfaceName].[MethodName] 형식으로 구현될 수도 있음. 이때는 Access Modifier 를 빼야하고, 호출 시 명시적 형변환이 필요함.
  • Property 는 만들 순 있는데 abstract 키워드 없이 자동으로 Abstract Property 임.

Interface 는 Interface 로 상속할 수 있음. 어셈블리(cf. dll, …) 에 있어서 코드변경을 못하거나, 기존 Interface 는 그대로 두고 추가기능을 넣고 싶을 때 사용함.

Interface 는 Class 에 대해서 다중상속이 가능함.

Struct

값 형식 이므로 깊은 복사 를 하고 new 가 없어도 됨.

System.Object 를 상속하는 System.ValueType 으로부터 상속됨.

c++ 과 다르게 기본이 private 임.

파라미터가 없는 생성자는 만들 수 없고, 생성자는 멤버변수를 모두 초기화 시켜야함.

Generic Programing

where [형식매개변수] : 제약조건

Code
    class GGG<T> where T : AAA, new()
    {
        public T Do1() { 
            T b = new AAA() as T;
            b.Print();
            return new T();
        }
        public TT Do2<TT>() where TT : struct 
        {
            TT res = new TT{ };
            Console.WriteLine(10); 
            return res;
        }
    }


제약조건

제약
설명
where T : struct T 는 값형식
where T : class T 는 참조형식
where T : new() T 는 매개변수가 없는 생성자 있음
where T : [클래스이름] T 는 기반 클래스의 파생클래스
where T : [인터페이스 이름] T 는 명시한 인터페이스를 반드시 구현
where T : struct T 는 값형식
where T : [형식매개변수] T 는 형식매개 변수로부터 상속받음

조건에 맞지 않은 형식 매개 변수를 넣으면 c++ 의 템플릿처럼 컴파일 에러가 남.

Collection

Array

Code
    static void Main(string[] args)
    {
        int[] a = new int[5] { 1, 2, 3, 4, 5 };
        int[] b = new int[] { 1, 2, 3, 4, 5 };
        int[] c = { 1, 2, 3, 4, 5 };
        int[,] f = new int[2, 4] { { 1, 2, 3, 4 }, { 1, 2, 3, 4 } }; // 2d array
        int[][] g = new int[3][] { new int[] { 1, 2, 3 }, new int[] { 1, 2, 3, 4}, new int[] { 1, 2 } }; // jagged array
    }


System.Array 클래스에 대응됨.

  • Static Method 로 Sort<T>(), BinarySearch<T>(), IndexOf(), FindIndex<T>(), ForEach<T>() 등을 가짐.
  • 참조타입이며Resize<T>(ref array) 처럼 ref 가 붙는 함수로는 새 배열의 주소를 할당받게됨.

Collection

object 기반 Collection

ArrayList, Queue, Stack, HashTable

  • Boxing, Unboxing 으로 모든 자료형을 담을 수 있지만 성능저하가 꽤 큼
  • System.Collections 에 있음.

Generic Collection

List<T>, Queue<T>, Stack<T>, Dictionary<TKey, TValue>

  • 쓸데없는 형식변환과 잘못된 형식 지정이 없음.
  • System.Collections.Generic 에 있음

특수기능

CompaireTo()

모든 타입은 IComparable<T> 을 상속해서 비교연산을 구현하고 있음.

foreach

Code
    public class TTT : IEnumerable, IEnumerator
    {
        private int[] data = { 1, 2, 3, 4, 5 };
        private int pos = -1;
        public object Current {  get { return data[pos]; } }
    
        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < data.Length; i++)
                yield return data[i];  // for 문에서 위치를 기억해 다시 호출시 이어함
        }
    
        public bool MoveNext()
        {
            return ++pos < data.Length;
        }
    
        public void Reset()
        {
            pos = -1; // 맨 앞의 앞요소
        }
    }


IEnumerableIEnumerator 를 상속하며 Genric 버전인 IEnumerable<T>, IEnumerator<T> 도 가능함.

댓글남기기