2015년 3월 8일 일요일

뇌자극 C# 5.0 - 11~12강

-일반화 프로그래밍-


11.1 일반화 프로그래밍이란?


특수한 개념으로부터 공통된 개념을 찾아 묶는 것을 "일반화"라고 한다.
일반화 프로그래밍은 데이터 형식을 묶는 것.
기능은 같으나 데이터 형식만 다른 경우 일반화를 시켜서 하나로 묶어서 구현하는 것

11.2 일반화 메소드


일반화 메소드는 이름처럼 데이터 형식을 일반화한 메소드이다.
일반화할 형식이 들어갈 자리에 구체적인 형식의 이름 대신 형식 매개변수가 들어간다.

한정자 반환형식 메소드이름<형식매개 변수> (매개변수목록)
{
  //...
}

예제)

//int 버전
void CopyArray( int[] source, int[] target )
{
   for(int i = 0; i < source.Length; i++ )
        target[i] = source[i];
}

//string 버전
void CopyArray( string[] source, string[] target )
{
   for(int i = 0; i < source.Length; i++ )
        target[i] = source[i];
}

를 아래와 같이 일반화 할 수 있다.

void CopyArray<T> ( T[] source, T[] target )
{
   for(int i = 0; i < source.Length; i++ )
        target[i] = source[i];
}

11.3 일반화 클래스


일반화 클래스는 데이터 형식을 일반화한 클래스.

class 클래스 이름 <형식매개 변수>
{
    //....
}

예제)
class Array_Int
{
    private int[] array;
    //...
    public int GetElement(int index){ return array[index]; }
}

class Array_Double
{
    private double[] array;
    //...
    public double GetElement(int index){ return array[index]; }
}

를 아래와 같이 일반화 할 수 있다.

class Array_Generic< T >
{
    private T[] array;
    //...
    public T GetElement(int index){ return array[index]; }
}

Array_Generic 클래스 사용하는 법

Array_Generic<int> intArr = new Array_Generic<int>();
Array_Generic<double> dbArr = new Array_Generic<double>();

11.4 형식 매개 변수 제약시키기


일반화 메소드나 일반화 클래스가 입력받는
형식 매개 변수 T는 "모든"데이터 형식을 대신할 수 있다.
특정 조건을 갖춘 형식에만 대응하는 형식 매개 변수가 필요할 때
형식 매개 변수의 조건에 제약을 줄 수 있다.

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

where T : struct  => T는 값 형식이어야 한다.
where T : class  => T는 참조 형식이어야 한다.
where T : new() => T는 반드시 매개 변수가 없는 생성자가 있어야 한다.
where T : 기반_클래스_이름  => T는 기반_클래스의 파생 클래스여야 한다.
where T : 인터페이스_이름  => T는 명시한 인터페이스를 반드시 구현해야 한다.
where T : U  => T는 또 다른 형식 매개 변수 U로부터 상속받은 클래스여야 한다.

11.5 일반화 컬렉션


컬렉션은 object 형식을 기반으로 하고 있기에
모든 형식 데이터를 담을 수 있는 장점이 있다.
하지만 object 형식을 기반으로 하기 있기에 성능의 문제를 가지고 있기도 하다.
컬렉션의 요소에 접근할 때 마다 형식 변환이 일어나야 하기 때문이다.

일반화 컬렉션은 컴파일 할 때 사용할 형식이 결정되기에
쓸데 없는 형식 변환을 일으키지 않아 성능에 문제가 없다.

System.Collections.Generic 네임스페이스에 다양한 컬렉션 클래스를 담고 있다.

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

위의 4개 일반화 클래스는 비일반화 클래스와 사용법과 기능이 같다.
단, 형식 매개 변수로 입력한 형식 외에는 입력을 허용하지 않는다.

-예외 처리하기-

12.1 예외에 대하여

예외 처리가 왜 중요하냐 하면, 프로그램이 실행중에 아무런 메세지 없이
그냥 오류가 나서 종료되어 버린다면 아무도 그 프로그램은 사용하지 않을 것이다.
그나마 고객에게 덜 욕먹기(?) 위해서는
무슨 오류가 나서 종료되는지 알려주는 것이 예외처리다.

12.2 try~catch로 예외 받기

예외를 받을 때 아래와 같은 형식으로 하면 된다.
try
{
    //실행하고자 하는 코드
}
catch(예외_객체1)
{
   //예외가 발생했을 때의 처리
}
catch(예외_객체2)
{
   //예외가 발생했을 때의 처리
}

12.3 System.Exception 클래스

try
{
}
catch(IndexOutOfRangeException e)
{
   //...
}
catch(DivideByZeroException e)
{
   //...
}

위와 같은 형식을 하나의 catch 절로 처리 할 수 있다.
try
{
}
catch( Exception e )
{
   //.....
}

Exception 클래스를 무조껀  사용하는 것은 금물이다.
프로그래머가 발생할 것으로 계산한 예외 말고도 다른 예외까지 받아내기에
처리하지 않아야 할 예외까지 처리하는 일은 없도록 해야 한다.

12.4 예외 던지기


try~catch 문으로 예외를 받는다는 것은 어디선가 예외를 던진다는 것이다.
예외를 던지는 법은 throw문을 이용해서 던진다.

try
{
   //...
   throw new Exception("예외를 던집니다.");
}
catch(Exception e)
{
   Console.WriteLine(e.Message);
}

12.5 try~catch 와 finally


try 블록에서 코드를 실행하다가 예외를 던져지면 바로 catch 절로 바로 뛰어 넘어온다.
예외 때문에 try블록 안에 있는 중요한 코드를 미처 실행하지 못하고 예외 처리가 된다.
예외 처리가 되어도 반드시 실행해야 하는 코드는 finally 블록안에 지정하면 된다.

try
{
   //...
   dbconn.Open(); //DB 연결
}
catch(Exception e)
{
   Console.WriteLine(e.Message);
}
finally
{
   dbconn.Close(); //예외처리가 되어도 반드시 db 연결은 끊는다.
}

12.6 사용자 정의 예외 클래스 만들기


Exception 클래스를 상속하면 새로운 예외 클래스를 만들 수 있다.

class MyException : Exception
{
   //...
}


2015년 3월 6일 금요일

뇌자극 C# 5.0 - 10강

-배열과 컬렉션, 그리고 인덱서-


10.1 All for one, one for all


같은 성격을 띤 다수의 데이터를 한번에 다뤄야 하는 경우 배열을 사용한다

데이터형식[] 배열이름 = new 데이터형식[용량]

예제)

int[] scores = new int[5];

scores[0] = 80;
scores[1] = 74;
scores[2] = 81;
scores[3] = 90;
scores[4] = 34;

foreach(int score in scores)
   Console.WriteLine(score);

10.2 배열을 초기화 하는 세 가지 방법


1) string[] array1 = new string[3]{ "배열의", "용량을", "명시하는 방법"};

2) string[] array2 = new string[]{ "배열의", "용량을", "생략하는 방법"};

3) string[] array3 = { "new키워드도", "생략하고", "초기화하는 방법"};

10.3 알아두면 삶이 윤택해지는 System.Array


Array 클래스의 주요 메소드와 프로퍼티

Sort() : 배열을 정열
BinarySearch<T>() : 이진 탐색을 수행합니다.
IndexOf() : 배열에서 찾고자하는 특정 데이터의 인덱스를 반환
TrueForAll<T>() : 배열의 모든 요소가 지정한 조건에 부합하는지 여부를 반환
FindIndex<T>() : 배열에서 지정한 조건에 부합하는 첫 번째 요소의 인덱스 반환
Resize<T>() : 배열의 크기를 재조정
Clear() : 배열의 모든 요소를 초기화
ForEach<T>() : 배열의 모든 요소에 대해 동일한 작업을 수행
GetLength() : 배열에서 지정한 차원의 길이를 반환
Length : 배열의 길이를 반환
Rank : 배열의 차원을 반환

10.4 2차원 배열


데이터형식[,] 배열이름 = new 데이터형식[2차원길이, 1차원길이];

예제)
int[, ]array = new int[2,3];
array[0,0] = 1;
array[0,1] = 2;
array[0,2] = 3;
array[1,0] = 4;
array[1,2] = 5;
array[1,3] = 6;

2차원 코드를 읽을 때는 []안에 있는 차원의 길이를 뒤에서 읽으면 이해하기 쉽다.
예를 들어 int[2,3]은

1,2,3
4,5,6

이다.

2차원 배열을 선언과 동시에 초기화 하는법

int[,] arr = new int[2,3]{ {1,2,3}, {4,5,6} };  //배열의 형식과 길이 명시
int[,] arr = new int[,]{ {1,2,3}, {4,5,6} };  //배열의 길이 생략
int[,] arr = { {1,2,3}, {4,5,6} };  //형식과 길이를 모두 생략

10.5 다차원 배열


차원이 둘 이상인 배열

예제)
int[, ,] array = new int[4,3,2]
                {
                    {{1,2},{3,4},{5,6}},
                    {{1,4},{3,4},{5,3}},
                    {{4,6},{5,5},{2,1}},
                    {{3,5},{3,6},{5,5}}
                }

10.6 가변 배열


직사각형이 아닌 필요한 부분만 데이터를 넣는 배열 형식

데이터형식[][] 배열이름 = new 데이터형식[가변 배열의 용량][];

예제)
int[][] jagged = new int[3][]
jagged[0] = new int[5]{1,2,3,4,5};
jagged[1] = new int[]{10,20,30};
jagged[2] = new int[]{100, 200};

[1][2][3][4][5]
[10][20][30]
[100][200]

10.7 컬렉션 맛보기


컬렉션 = 같은 성격을 띄는 데이터의 모음을 담은 자료구조
ArrayList, Queue, Stack, HashTable

10.7.1 ArrayList


배열과 비슷한 컬렉션이지만 용량을 지정할 필요 없이
자동으로 용량이 바뀌는 특성이 있다.
그리고 배열과 다르게 다양한 형식의 객체를 담을 수 있다.

예제)
ArrayList list = new ArrayList();
list.Add(10);  //인덱스 번호는 0부터 시작
list.Add(20);  //1
list.Add(30);  //2

list.RemoveAt(1);  //20을 삭제
list.Insert(25, 1);  //25를 1번 인덱스에 삽입 즉, 10과 20사이에 25를 삽입

10.7.2 Queue


Queue는 대기열이라는 뜻이다.
데이터나 작업을 차례대로 입력해뒀다가 입력된 순서대로 하나씩 꺼내 처리하기 위해 사용
데이터 입력시 = Enqueue() 메소드 사용
데이터 출력시 = Dequeue() 메소드 사용

예제)
//큐에 데이터 입력
Queue que = new Queue();
que.Enqueue(1);
que.Enqueue(2);
que.Enqueue(3);
que.Enqueue(4);

//큐에서 데이터 출력
while(que.Count > 0)
     Console.WriteLine(que.Dequeue());


10.7.3 Stack


스텍은 큐와 반대로 먼저 들어온 데이터가 나중에 나가고,
나중에 들어온 데이터가 먼저 나가는 구조의 컬렉션

데이터 입력시 = Push() 메소드 사용
데이터 출력시 = Pop() 메소드 사용

예제)

Stack stack = new Stack();
stack.Push(1);
stack.Push(2);
stack.Push(3);

int a = (int)stack.Pop();  // a = 3

10.7.4 Hashtable


Hashtable는 키(Key)와 값(Value)의 쌍으로 이루어진 데이터를 다룰 때 사용
탐색 속도가 빠르고, 사용하기도 편하다.

Hashtable ht = new Hashtable();
ht["book"] = "책";
ht["cook"] = "요리사";
ht["tweet"] = "지저귀다";

Console.WriteLine( ht["book"]);
Console.WriteLine( ht["cook"]);
Console.WriteLine( ht["tweet"]);

해쉬테이블 컬렉션은 키 데이터를 그대로 사용한다. 어떤 형식이든 키로 사용가능하다.
키를 이용해서 단번에 데이터가 저장되어 있는 컬렉션 내의 주소를 계산한다.
이 작업을 해싱이라고 한다.

10.8 인덱서


인덱서는 인덱스를 이용해서 객체 내의 데이터에 접근하게 해주는 프로퍼티
객체를 배열처럼 사용할 수 있게 해준다.

class 클래스이름
{
    한정자 인덱서형식 this[형식 index]
    {
       get
       {
          //index를 이용하여 내부 데이터 반환
       }
       set
       {
          //index를 이용하여 내부 데이터 저장
       }
    }
}

예제)
class MyList
{
    private int[] array;

    public MyList()
    {
       array = new int[3];
    }
    public int this[int index]
    {
       get
       {
           return array[index];
       }
       set
       {
          if(index >= array.Length)
          {
              Array.Resize<int>(ref array, index + 1);
              Cosole.WriteLine("Array Resized : {0}", array.Length);
          }
          array[index] = value;
       }
    }
}

프로퍼티는 객체 내의 데이터에 접근할 수 있도록 하는 통로다.
인덱서도 프로퍼티처럼 객체 내의 데이터에 접근할 수 있도록 하는 통로다.
프로퍼티와 다른 점은 인덱스를 이용한다는 것.

뇌자극 C# 5.0 - 8~9강

-8강 인터페이스와 추상 클래스-


8.1 인터페이스의 선언


interface 인터페이스이름
{
   반환형식 메소드이름1( 매개_변수_목록 );
   반환형식 메소드이름2( 매개_변수_목록 );
   반환형식 메소드이름3( 매개_변수_목록 );
   반환형식 메소드이름4( 매개_변수_목록 );
   ......
}

인터페이스는 메소드, 이벤트, 인덱서, 프로퍼티만 가질 수 있다.
그리고 구현부와 접근 제한자도 없다. 무조껀 public로 선언된다.
인스턴스도 만들 수 없다.
단, 인터페이스를 상속 받는 클래스의 인스턴스를 만드는 것은 가능

8.2 인터페이스는 약속이다


인터페이스는 PC에 있는 USB 포트와 비슷하다.
모양이 규격화 되어 있어서 모양만 맞으면 어떤 제품이던 꽂아서 쓸수 있다.
인터페이스에 선언된 메소드들은 상속 받는 클래스에서 반드시 구현을 해야만 한다.
꼭 들어가야 하는 메소드를 인터페이스로 선언해 놓는 것이 좋다.

8.3 인터페이스를 상속하는 인터페이스


기존 인터페이스에 새로운 기능을 추가한 인터페이스를 만들고 싶을 때
인터페이스를 상속하는 인터페이스를 만들면 된다.

interface 파생인터페이스 : 부모인터페이스
{
    //..... 추가할 메소드 목록
}

8.4 여러개의 인터페이스, 한꺼번에 상속하기


클래스는 여러 클래스를 한꺼번에 상속할 수 없다.
C#에서는 클래스의 다중 상속을 허용하지 않는다.
하지만 인터페이스는 내용이 아닌 외형을 물려주기 때문에
인터페이스의 다중 상속은 허용한다.

예제)
interface IRunnable
{
   void Run();
}
interface IFlyable
{
   void Fly();
}

class FlyingCar : IRunnable, IFlyable  //인터페이스 다중 상속
{
    public void Run()
    {
        Console.WriteLine("Run! Run!");
    }
    public void Fly()
    {
        Console.WriteLine("Fly! Fly!");
    }
}

8.5 추상 클래스 : 인터페이스와 클래스 사이


추상 클래스는 인터페이스와 달리 "구현"을 가질 수 있다.
하지만 클래스와는 달리 "인스턴스"는 가질 수 없다.
그리고 "추상 메소드"를 가질 수 있다

추상 클래스 선언하는 법

abstract class 클래스이름
{
   //클래스와 동일하게 구현
}

예제)
abstract class AbstractBase
{
   public abstract void SomeMethod();
}

class Derived : AbstractBase
{
   public override void SomeMethod();
   {
      //Something
   }
}

추상 메소드는 추상 클래스를 사용하는 프로그래머가 그 기능을 정의하도록 강제하는 장치

-9강 프로퍼티-


9.1 public 필드의 유혹


프로퍼티를 이용하면 으닉성과 편의성을 다 누릴수 있다.
자바 같은 경우에는 아래와 같이 쓴다.

class MyClass
{
   private int myField;
   public int GetMyField() { return myField;}
   public void SetMyField() ( int NewValue ) { myField = newValue;}
}

MyClass obj = new MyClass();
obj.SetMyField(3);

하지만 C#은 프로퍼티를 지원한다.

9.2 메소드보다 프로퍼티


프로퍼티를 선언하는 문법

class 클래스이름
{
   데이터형싱 필드이름;

   접근한정자 데이터형식 프로퍼티이름
   {
       get
       {
           return 필드이름;  
       }

       set
       {
            필드이름 = value;
       }
   }
}

get/set은 접근자라고 한다.
get 접근자는 값을 읽어 오고, set 접근자는 필드에 값을 할당 한다.
위의 소스를 프로퍼티로 바꿔보겠다.

class MyClass
{
   private int myField;
   public int MyField
   {
      get
      {
         return myField;
      }
      set
      {
          myField = newValue;
      }
   }
}

MyClass obj = new MyClass();
obj.MyField = 3;

set 접근자를 구현하지 않으면 해당 프로퍼티는 읽기 전용이 된다.

9.3 자동 구현 프로퍼티


C# 3.0 이상부터는 코드를 더 단순하게 만드는 자동 구현 프로퍼티를 도입했다.

예제)
public class NameCard
{
    private string name;
    private string phoneNumber;

    public string Name
    {
       get { return name; }
       set { name = value; }
    }
    public string PhoneNumber
    {
       get { return phoneNumber; }
       set { phoneNumber = value; }
    }
}

를 자동 구현 프로퍼티로 바꾸면....

public class NameCard
{
    public string Name
    {
       get; set;
    }

    public string PhoneNumber
    {
        get; set;
    }
}

9.4 프로퍼티와 생성자


객체를 생성할 때 각 필드를 초기화 하는 또 다른 방법은 프로퍼티를 이용한 초기화다.

클래스이름 인스턴스 = new 클래스이름()
{
    프로퍼티1 = 값,
    프로퍼티2 = 값,  //세미클론(;)이 아니라 콤마(,) 다
    프로퍼티3 = 값
}; //세미콜론(;)이 붙어야 한다.

모든 값이 올 필요는 없고 초기화 하고 싶은 프로퍼티만 넣어서 초기화 하면 된다.

예제)
BirthdayInfo birth = new BirthdayInfo()
{
   Name = "서현",
   Birthday = new DateTime(1991, 6, 28)
};

내가 서현을 좋아하긴 하지만....;; 진짜 책에 이리 예제가 되어 있다...;

9.5 무명 형식


말 그래도 이름이 없는 형식이다. 무명 형식은 선언과 동시에 인스턴스를 할당한다.
인스턴스를 만들고 다시는 사용하지 않을 때 요긴하게 쓰인다.

예)
var myInstance = new { Name = "윤아", Age="25" }; //new 다음에 이름이 없다.

9.6 인터페이스의 프로퍼티


인터페이스는 메소드 뿐만 아니라 프로퍼티와 인덱서도 가질 수 있는데
프로퍼티나 인덱서를 가진 인터페이스를 상속하는 클래스가 "반드시" 해당 프로퍼티와
인덱서를 구현해야 한다.
인터페이스의 프로퍼티 선언이 클래스의 자동 구현 프로퍼티 선언과 동일하다.

예제)
interface IProduct
{
    string ProductName
    {
        get; set;
    }
}

class Product : IProduct
{
    private string productName;
    public string ProductName
    {
       get { return productName; }
       set { productName = value; }
    }
}

9.7 추상 클래스와 프로퍼티


추상 프로퍼티 문법

abstract class 추상클래스이름
{
   abstract 데이터형식 프로퍼티이름
   {
      get; set;
   }
}

예제)

abstract class Product
{
   private static int serial = 0;
   public string SerialID
   {
      get { return String.Format("{0:d5}", serial++) }
   }
   abstract public DateTime ProductDate
   {
       get; set;
   }
}

class MyProduct : Product
{
   public override DateTime ProductDate
   {
      get; set;
   }
}

뇌자극 C# 5.0 - 7강 - 2

7강이 워낙 길어서 2개로 나눴다 -_-;

7.10 오버라이딩과 다형성


다형성 : 객체가 여러 형태를 가질 수 있음을 뜻한다.
상속받아 만들어진 파생 클래스를 통해 다형성을 실현한다

예제)
class ArmorSuite
{
    public virtual void Initialize()
    {
       Cosole.WriteLine("Armored");
    }
}

class IronMan : ArmorSuite
{
   //...
}

class WarMachine : ArmorSuite
{
   //...
}

ArmorSuite의 옵션을 바꿔주려면 Initialize()를 재정의 해줘야 한다
하위에서 상위의 메소드를 바꾸는 것을 오버라이딩(Overriding)라고 한다.

메소드를 오버라이딩 하려면 한가지 조건이 필요한데.
기반 클래스의 메소드가 virtual 키워드로 한정되어 있어야 한다.

하위 클래스에서는 컴파일러에게 재정의 한다는 것을 알려주기 위해
override로 한정해줘야 한다.

class IronMan : ArmorSuite
{
    public override void Initialize()
    {
        base.Initialize();
        Console.WriteLine("Repulsor Rays Armed");
    }
}

class WarMachine : ArmorSuite
{
    public override void Initialize()
    {
        base.Initialize();
        Console.WriteLine("Double-Barrel Cannons Armed");
        Console.WriteLine("Micro-Rocket Launcher Armed");
    }
}

7.11 메소드 숨기기

기반 클래스에서 구현된 버전의 메소드를 감추고 
파생 클래스에서 구현된 버전만 보여주는 것

파생 클래스 버전의 메소드를 new 한정자로 수식하면 된다.
(생성자 호출할 때의 new와 다른 기능이다.이름만 같다.)

예제)
class Base
{
   public void MyMethod()
   {
      Console.WriteLine("Base.MyMethod()");
   }
}

class Derived : Base
{
    public new void MyMethod()
    {
       Console.WriteLine("Derived.MyMethod()");
    }
}

7.12 오버라이딩 봉인하기


클래스가 상속 불가로 만들려면 sealed 를 class 앞에 붙이면 된다.
메소드를 오브라이드를 못하게 하려면 역시 sealed를 매소드 앞에 붙이면 된다.
단, virtual로 선언된 가상 메소드를 오버라이딩한 메소드만 가능하다

7.13 구조체


복합 데이터 형식에는 클래스 말고도 구조체가 있다.
struct 키워드를 사용해서 선언한다.

-클래스와 구조체의 차이점-

클래스 - 참조형식 
구조체 - 값형식

클래스 - 얕은 복사 
구조체 - 깊은 복사

클래스 - new 연산자와 생성자 필요
구조체 - 선언만으로도 생성

클래스 - 상속 가능
구조체 - 상속 불가

클래스 - 매개변수 없는 생성자 선언 가능
구조체 - 매개변수 없는 생성자 선언 불가능

뇌자극 C# 5.0 - 7강 - 1

클래스

7.1 객체 지향 프로그래밍과 클래스


객체가 가지고 있는 두 가지, 속성과 기능.
속성 = 데이터(변수), 기능 = 메소드

클래스 = 객체를 만들기 위한 장치

7.2 클래스의 선언과 객체의 생성


class 클래스이름
{
    //데이터와 메소드
}

예제)
class Cat
{
    //데이터(필드)
    public string Name;
    public string Color;
 
    //메소드
    public void Meow()
    {
        Console.WriteLine("{0} : 야옹", Name);
    }
}

객체 생성법

Cat kitty = new Cat();
kitty.Color = "하얀색";
kitty.Name = "키티";
kitty.Meow();
Console.WriteLine("{0} : {1}", kitty.Name, kitty.Color);

Cat nero = new Cat();
nero.Color = "검은색";
nero.Name = "네로";
nero.Meow();
Console.WriteLine("{0} : {1}", nero.Name, nero.Color);

7.3 객체의 삶과 죽음에 대하여 : 생성자와 소멸자


-생성자-

생성자의 역할 = 객체를 생성하는 것.

class 클래스이름
{
   한정자 클래스이름( 매개변수 목록 )
   {
       //
   }
   //필드
   //메소드
}

생성자를 구현해야 하는 이유
= 객체를 생성하는 시점에 객체의 상태를 원하는 값으로 초기화 하고 싶을 때

예제)

class Cat
{
   public Cat()
   {
      Name = "";
      Color = "";
   }
   public Cat( string _Name, string _Color )
   {
      Name = _Name;
      Color = _Color;
   }
}

-소멸자-

객체를 소멸할 때 쓰는 소멸자
가비지 컬렉터가 객체가 소멸되는 시점을 판단하여 소멸자를 호출

class 클래스이름
{
   ~클래스이름()
   {
      //
   }
   //필드
   //메소드
}

7.4 정적 필드와 메소드


static = 메소드나 필드가 클래스의 인스턴스가 아닌 클래스 자체에 소속되도록 지정

예 - 인스턴스에 소속된 필드의 경우)

class MyClass
{
   public int a;
   public int b;
}

//

public static void Main()
{
    MyClass  obj1 = new MyClass();
    obj1.a = 1;
    obj1.b = 2;
}

예 - 클래스에 소속된 필드의 경우(static))

class MyClass
{
   public static int a;
   public static int b;
}

//

public static void Main()
{
   MyClass.a = 1;
   MyClass.b = 2;
}

정적 필드와 메소드를 사용하면 객체를 만들 필요 없이 바로 사용가능하다.
프로그램 전체에 걸쳐 공유해야하는 변수가 있다면 정적 필드를 이용하면 된다.

7.5 객체 복사하기 : 얕은 복사와 깊은 복사


얕은 복사 : 객체를 복사할 때 참조만 복사하는 것(같은 곳을 참조한다)
깊은 복사 : 객체를 복사할 때 참조와 값까지 복사하는 것 (서로 각자 다른 곳을 참조한다)

7.6 this 키워드


객체 외부에서는 객체의 필드나 메소드에 접근할 때 객체의 이름을 사용한다면,
객체 내부에서는 자신의 필드나 메소드에 접근할 때 this 키워드를 사용한다.

예)

class Employee
{
   private string Name;
   public void SetName( string _Name )
   {
      this.Name = _Name;
   }
}

7.7 접근 한정자로 공개 수준 결정하기


클래스에 선언되어 있는 필드와 메소드 중에
어떤 것들을 공개하고 비공해 할 것인지 결정하는 한정자

public :  클래스의 내부/외부 모든 곳에서 접근할 수 있다.

protected : 클래스의 외부에서는 접근할 수 없지만, 파생 클래스에서는 접근 가능

private : 클래스의 내부에서만 접근할 수 있다.(기본 한정자)

internal : 같은 어셈블리에 있는 코드에 대해서만 public로 접근 가능. 다른 어셈블리에 있는 코드에서는 private와 같은 수준의 접근성을 가짐

protected internal : 같은 어셈블리에 있는 코드에 대해서만 protected로 접근할 수 있다.
다른 어셈블리에 있는 코드에서는 private와 같은 수준의 접근성을 가진다.

7.8 상속으로 코드 재활용하기


class 기반 클래스
{
   //멤버선언
}
class 파생 클래스 : 기반 클래스
{
   //아무 멤버를 선언하지 않아도 기반 클래스의 모든 것을 물려 받아 갖게 된다.
   //단, private로 선언된 멤버는 제외
}

파생 클래스의 인스턴스를 생성할 때
호출되는 기반 클래스의 생성자에게 매개변수를 전달하려면 base 키워드를 사용한다
this는 자기 자신을 가리킨다면 base는 기반 클래스를 가르킨다.

예제)
class Base
{
    public void BaseMethod();
}

class Derived:Base
{
    public void DerivedMethod()
    {
       base.BaseMethod();
    }
}

7.9 기반 클래스와 파생 클래스 사이의 형식 변환, 그리고 is 와 as


기반 클래스와 파생 클래스 사이에서는 족보를 오르내리는 형식 변환이 가능하며,
파생 클래스의 인스턴스는 기반 클래스의 인스턴스로도 사용할 수 있다.

예제)
Mammal mammal = new Mammal();
mammal.Nurse();

mammal = new Dog();
mammal.Nurse();

Dog dog = (Dog)mammal;
dog.Nurse();
dog.Bark();

mammal = new Cat();
mammal.Nurse();

Cat cat = (cat)mammal;
cat.Nurse();
cat.Meow();

형변환을 위한 연산자 is, as

is : 객체가 해당 형식에 해당하는지 검사하여 그 결과를 bool 값으로 변환

as : 형식 변환 연산자와 같은 역할을 한다. 다만, 형변환 연산자가 변환에 실패하는 경우 예외를 던지는 반면, as 연산자는 객체 참조를 null로 만든다.

2015년 3월 5일 목요일

뇌자극 C# 5.0 - 6강

-메소드로 코드 간추리기-

6.1 메소드란?


메소드는 일련의 코드를 하나의 이름 아래 묶은 것.
이렇게 묶은 코드는 메소드의 이름을 불러주는 것만으로도 실행 가능

메소드 선언하는 형식

class 클래스의 이름
{
   한정자 반환형식 메소드의이름 (매개변수 목록)
   {
     실행하고자 하는 코드
     ....

     return 메소드의 결과;
   }
}

예제)

class Calculator
{
    public static int Puls(int a, int b)
    {
       Console.WriteLine("Input : {0}, {1}", a, b);
       int result = a + b;
       return result;
    }
}

int x = Calulator.Plue( 3, 4 ); //x는 7

6.2 return에 대하여


return문은 언제든지 메소드 중간에 호출되어 메소드를 종결시키고
프로그램의 흐름을 호출자에게 돌려주는 기능

6.3 매개 변수에 대하여


메소드 외부에서 메수드 내부로 데아터를 전달하는 매개체 역할을 하는 변수
한 변수를 또 다른 변수에 할당을 하면 변수가 담고 있는 데이터만 복사가 될 뿐이다.

메소드를 호출할 때 데이터를 복사해서 매개 변수에 넘기는 것을
"값에 의한 전달(Call by value)"라고 부른다.

6.4 참조에 의한 매개 변수 전달


값에 의한 전달은 매개 변수가 값을 복사해서 넘기기에 원본 변수가 변하지 않는다.
원본 변수를 변화 시키려면 "참조에 의한 매개 변수" 전달을 해야한다

참조에 의한 매개 변수 전달법은 ref 키워드를 쓰면 된다.

예)
static void Swap(ref int a, ref int b)
{
   int temp = b;
   b = a;
   a = temp;
}

6.5 출력 전용 매개 변수


대부분의 경우 메소드의 결과는 1개면 충분하다.
가끔 2개 이상의 결과 값이 필요한 경우에는 ref나 out 키워드를 사용한다.
C#에서는 out 키워드 쓸 것을 권장한다.

예)
void Divide( int a, int b, out int quotient, out int remainder )
{
    quotient = a / b;
    remainder = a % b;
}

int a = 20;
int b = 3;
int c = 0;
int d = 0;

Divide( a, b, out c, out d );

Console.WriteLine("Quotient : {0}, Remainder {1}", c, d);

6.6 메소드 오버로딩


오버로딩(Overloading)란? "과적하다"의 뜻을 가지고 있다.
하나의 메소드 이름에 여러 개의 구현을 올리는 것을 뜻한다.
(오버라이딩과 헷깔리는데 전혀 다른 뜻이다)

예제)

int Plus(int a, int b)
{
   return a + b;
}

double Plus(double a, double b)
{
   return a + b;
}

위를 보면 메소드 이름과 기능은 같고, 반환 형식과, 매개 변수 형식만 다르다.
메소드 오버로딩은 이름에 대한 고민을 줄여주고, 코드를 일관성 있게 유지해준다.

6.7 가변길이 매개 변수


가변길이 매개 변수란? 갯수가 유연하게 변할 수 있는 매개 변수를 말한다.

예)

int total = 0;

total = Sum(1, 2);
total = Sum(1, 2, 3);
total = Sum(1, 2, 3, 4);
total = Sum(1, 2, 3, 4, 5);
.........

위와 같이 Sum이라는 이름은 같고 매개 변수의 개수가 다르다고
각자 따로 만드는 것은 시간 낭비다.
가변길이 매개 변수는 params 키워드배열을 이용해서 선언한다.

int Sum( prams int[] args)
{
    int sum = 0;

    for(int i = 0; i<args.Length; i++)
    {
        sum += args[i];
    }
    return sum;
}

가변길이 매개 변수는 형식은 같으나, 매개 변수의 개수가 유연하게 달라질 때 적합하다.

6.8 명명된 매개 변수


메소드를 호출할 때 매개 변수 목록 중
어느 매개 변수에 데이터를 할당할 것인지를 결정하는 것은 "순서"다.

C#은 순서에 상관 없이 변수의 이름에 근거해서 데이터를 할당 할 수 있다.
방법은 변수 이름 뒤에 : 를 붙이고 그 뒤에 데이터를 넣으면 된다.

예제)
static void PrintProfile(string name, string phone)
{
    Console.WriteLine("Name:{0}, Phone:{1}", name, phone);
}

static void Main(string[] args)
{
   PrintProfile(name : "윤아", phone : "010-123-4567");
}

6.9 선택적 매개 변수


매개 변수를 특정 값으로 초기화 할 수 있다.

예)
void MyMethod( int a = 0, int b = 0 )
{
    Console.WriteLine( "{0},  {1}", a, b );
}

선택적 매개 변수는 항상 필수 매개 변수 뒤에 와야 한다.(매개 변수가 없는 경우는 제외)

예)
void MyMethod_0( int a = 0 )
{
   Console.WriteLine( "{0}", a );
}

void MyMethod_1( int a = 0, int b = 0 )
{
   Console.WriteLine( "{0}, {1}", a, b );
}

void MyMethod_2( int a = 0, int b, int c = 10, int d = 20 )
{
   Console.WriteLine( "{0}, {1}, {2}", a, b, c );
}

뇌자극 C# 5.0 - 4~5강

-4강 데이터를 가공하는 연산자-

산술 연산자 : +, -, *, /, %
증가/감소 연산자 : ++, --
관계 연산자 : <, >, ==, !=, <=, >=
조건 연산자 : ? 참:거짓
논리 연산자 : &&, ||, !
비트 연산자 : <<, >>, &, |, ^, ~
할당 연산자 : =, +=, -=, *=, %=, |=, ^=, <<=, >>=


-5강 코드의 흐름 제어하기-


1) if문

if(조건식)
{
    조건식이 참인 경우 실행할 코드;
}
else
{
    조건이 참이 아닌 경우 실행할 코드;
}

2) switch 문

switch(조건식)
{
    case 상수1:
        실행할 코드
        break;
    case 상수2:
        실행할 코드
        break;
    case 상수N:
        실행할 코드
        break;
    default: 
        실행할 코드
        break;
}

3) while 문

while (조건식)
{
   반복 실행할 코드;
}

4) do while 문

do
{
    반복 실행할 코드;
}
while(조건식); //;가 while문과 다른 점. do{}에 있는 코드는 최소 1번은 실행된다

5) for 문

for(초기화식; 조건식; 반복식;)
{
     반복 실행할 코드;
}

6) foreach 문

foreach(데이터형식 변수명 in 배열_또는_컬렉션)
{
    코드 또는 코드 블럭
}

7) 점프문

break : 반복 중지
continue : 한회 점프
goto : 강제 이동
return : 반환
throw : 예외처리