Now For Something Completely Different

1. Deterministic Object Cleanup

– 자원 반납을 제어하기 위해서, C#에서는 Dispose() 메소드를 가지고 있는 System.IDisposable 인터페이스를 제공한다.
– Dispose() 메소드로 자원 해제를 관리하려면, GC.SuppressFinalize(this); 이렇게 GC 클래스의 SuppressFinalize 메소드를 Dispose() 메소드 내에서 호출해 준다.
– C# also has some syntactic sugar via the using keyword that makes releasing the resources used by classes occur in a more deterministic manner via the Dispose method.
– using은 뭐야.. ㅠ.ㅠ;; 어렵군.

2. Delegates

– 메소드 포인터를 넘겨준다. 콜백 함수를 제공하기 위한 매카니즘.
– 이벤트 핸들러 등록할 때 사용.
– (스트레티지 패턴과 관련이 있을까..?)
– 만드는 순서
    – 콜백 함수로 호출되기 원하는 메소드의 파라미터와 리턴타입을 가진 delegate를 선언한다.

public delegate Mammal CallbackFunction(Dog d);

    – deletege를 파라미터로 받는 메소드를 정의한다.

    //create delegate using delegate object (old way)
    CallbackFunction myCallback = new CallbackFunction(BarkAndReturnHome);
    myCallback(dog);

    //create delegate using delegate inference (new way)
    CallbackFunction myCallback2 = BarkAndScareCat;
    myCallback2(dog);

    – 이제 delegate와 같은 메소드 시그너쳐를 가졌거나 covariant 리턴타입과 covariant 파라미터를 가진 메소드를 가지고 delegate의 인스턴스를 만들 수 있다. 그리고 이 녀석을 위에서 만든 delegate를 파라미터로 받는 메소드에 넘겨줄 수 있다.

public static Cat BarkAndScareCat(Dog d)
    {
    d.Speak();
    Cat c = new Cat();
    c.Speak();
    return c;
    }

– the same delegate can refer to static and instance
methods, even at the same time, since delegates are multicast.(먼소린지..)

3. Value Types (Structs)

– 스택에 객체가 살도록 할 수 있는데, int 같은 타입들이 그렇게 구현되어 있다.
– Value Type 들은 항상 값으로 전달되고, GC의 대상이 되지 않는다.
– Value Type의 배열은 레퍼런스가 아니라 실제 Value를 가지고 있다.
– class가 아니라 struct로 선언한다.
– 다른 생성자를 만들어도, 기본 생성자를 자동으로 만들어 주네;; 참조한 문서에서는 기본 생성자로 생성할 수 없다고 나와있었는데.. 흠..

4. Run Time Type Identification (as operator)

– 타입 캐스팅 할 때는 as 연산자를 사용할 수 있다.
– Value Type에는 사용할 수 없다.
– MyClass mc = o as MyClass;
– 캐스팅이 적절하지 않으면, null이 된다.

5. Properties

– 자바의 getter, setter 처럼 필드에 간접적으로 접근하도록 하는것이 가능하다.

    private string name;

    //property with public getter and private setter
    public string Name{

    get{
        return name;
    }  

    private set {
        name = value;
    }
    }

– 값 설정하기

User.MinimumAge = -5;

– 값 가져오기

Console.WriteLine(User.MinimunAge);

6. Multidimensional Arrays

– multidementional 배열과 jagged 배열을 구분한다.
– multidementional 배열은 모두 같은 길이의 배열을 가진 배열.
– jagged 배열은 다른 길이의 배열들을 가진 배열.

7. Indexers

– [ ] 를 재정의 하기 위한 특별한 문법.
– 아음.. pass

8. Preprocessor Directives

– C/C++에 있는 것중에 몇개만 남겨놨음.
– The primary functionality that remains is the ability to  #define and #undef identifiers and also the ability to select which sections of code to compile based on the validity of certain expressions via #if, #elif, and #else.
– #error: 컴파일 할 때 이 뒤에 적어준 메시지 출력하면서 에러 발생.
– #warning: 컴파일 할 때 이 뒤에 적어준 메시지 출력하면서 경고 발생.
– #pragma: 컴파일 경고 무시 해줌.
– #line: 컴파일 에러 발견했을 때 소스 라인 알려주고 싶을 때 사용.

9. Aliases

– C/C++의 typedef 처럼 풀 패키지 경로를 가진 클래스의 별칭을 만들 때 using 사용.
– 다른 네임스페이스 존재하는 같은 클래스 이름을 가진 클래스들을 지칭할 때 이용 하겠군.
using Terminal = System.Console;

10. Runtime Code Generation

– 자바에서 런타임에 바이트코드를 생성해서 로딩할 수 있는 것처럼 C#에서는 Reflection.Emit 네임스페이스에 들어있는 녀석들을 사용해서 그런 걸 할 수 있다.

11. Pointers and Unsafe Code

– 포인터를 사용하는 블럭을 지정할 수 있다.
– unsafe 키워드로 블럭을 지정하고 컴파일 할 때 /unsafe 옵션을 준다.
– GC가 변수의 메모리 위치를 런타임 중에 변경할 수 있기 때문에, 포인터를 쓰려면 fixed 키워드로 메모리 위치를 런타임에 변경하지 않도록 설정해야 한다.
– 왜 포인터를 쓰고 싶을까?

12. Pass by Reference

– 자바는 전부 Pass by value
– C#에서는 Reference도 넘길 수 있다. 메소드 파라미터에 ref나 out 키워드를 사용한다. ref 키워드를 사용할 떄는 반드시 초기화가 된 상태여야 한다.

13. Verbatim Strings

– 문자열 앞에 @를 붙여서 \도 그냥 문자로 인식하게 할 수 있다.
string filename2 =  "C:\\My Documents\\My Files\\File.html"; // 대신에
string filename  = @"C:\My Documents\My Files\File.html";  //요렇게

14. Overflow Detection

- 변수 타입 변환 할 때, 큰녀석을 작은 그릇에 넣을 때 오버플로우가 발생할 수 있는데, 이 예외를 평상시엔 무시하다가 컴파일 옵션으로 /checked+ 이걸 주면 그 때는 예외 발생시켜준다.
- checked 블럭을 사용해서 항상 이 예외를 잡도록 할 수도 있다.
- unchecked 블럭을 사용해서 항상 이 예외를 무시하도록 할 수 있다.

15. Explicit Interface Implementation

- 같은 이름의 메소드를 가지고 있는 두 개의 인터페이스를 구현할 때 자바는 그냥 하나의 메소드를 구현하는 수밖에 없다.
- C#은 각각의 인터페이스 구현체에 해당하는 메소드를 구현할 수 있다. 메소드 이름앞에 인터페이스이름. 을 붙여준다.
- 사용할 때는 대신 타입을 해당 타입으로 캐스팅 한 다음에 써야 한다. 인터페이스를 구현한 클래스 타입으로 쓰면 안 된다.(에러다.)

16. Friend Assemblies

- 해당 assmbly를 다른 assembly에 노출 시킬 수 있다. [assembly:InternalsVisibleTo("friend_assembly_test_2")]
- internal 변수는 assembly에서 바로 접근할 수 있다.
Console.WriteLine(f2.secret);

17. The Namespace Qualifier

- 네임스페이스의 충돌을 방지하기 위해서 :: 의 왼쪽에는 스콥, 오른쪽에는 네임스페이스로 구분할 수 있다.
global::System.Console.WriteLine("The time is " + Console);

18. Iterators (Continuations)

- foreach 루프로 돌리려면 in 다음에 오는 녀석이 System.Collections.IEnumerable 타입이어야 한다.
- yield를 사용하면, 특정 메소드나 프로퍼티를 iterator로 변환해 준다.
- yield return를 사용해서 하나씩 넘겨줄 수도 있다.
- 여러 콜렉션을 이터레이트 하고 싶은 때 사용하면 되겠군.

19. Partial Types

- 클래스 하나, Struct 하나, 인터페이스 하나를 여러 파일에 걸쳐서 작성하는 것이 가능하다.
- partial 키워드를 class앞에 사용한다.
- 하나의 파일에서는 private으로 하고 하나의 파일에서는 public으로 하는 것은 안된다.

20. Static Classes

- 정적인 클래스를 만들 수 있는데, 이 녀석은 base 클래스가 될 수도 없고, 인스턴스 멤버를 가질 수도 없다.
-static 키워드를 class 앞에 붙여준다.
- 유틸 클래스 만들 때 쓰나보다.

21. Nullable Types

- System.Nullable 타입의 객체는 null 될 수 있다.
- Value Type 들도 변수 선언할 때 타입 뒤에 ?를 붙여 주면 null 값을 가질 수 있다.
int? x = 5;  // Nullable<int> 와 동일.
- ?? 연산자는 해당 value type이 null 일 때 오른쪽에 있는 인자의 값을 왼쪽의 변수에 대입한다.
x ?? y; // x == (null ? y : x);

22. Anonymous Methods

- delegate에 넘겨줄 콜백 메소드 인스턴스를 마치 Java에서 anonymous class 정의하듯이 메소드 이름이 들어갈 위치에 메소드를 구현하는 기법.

    /* anonymous code block */
    CallbackFunction cf = delegate (string a, int b){
                             for(int i = 0; i < b ; i++)
                               Console.WriteLine("{0}.) {1}", i + 1, a); };

- goto, break, continue 키워드를 사용해서 anonymous method 경계를 넘나들면 안 된다.
- ref, out 파라미터로 anonymous method 경계 밖에 있는 녀석들을 받아오면 안 된다.

큐브 맞추기와 개발

아음 그놈의 미국 비자 때문에 신경을 하두써서 눈 및에 다크써클까지 생겼습니다. 에효.. 오늘은 힘들어서 잡담이나 간략하게…

얼마전 반디앤루이스에 갔다가 조그만 큐브를 발견하고 바로 질렀습니다. 3천원.

사용자 삽입 이미지
그림출처 : http://www.onhobby.com/shop/shopdetail.html?brandcode=009000000001&search=&sort=order

굉장히 귀엽습니다. 그리고 완전 조그맣기 때문에, 주머니에 넣고 다니면서 전철 이동중이거나 화장실 갈 때 가지고 가서 놀기 좋더군요. 맞추는 방법도 쉬워서 30분만 인터넷에 떠도는 매뉴얼대로 따라하면 맞출 수 있습니다. 공식이 한 개입니다. 그 공식만 외우고 돌리다 보면 맞게 되어있습니다. 문제는 도대체 내가 맞추긴 맞췄는데 어떻게 맞춰진 건지 모르겠다는 거죠.

개발도 마찬가지가 아닐까 생각해봤습니다. 예전 마소에 토비형(호칭 적응 중)이 기고하신 글 중에, 큐브 맞추기와 개발자의 학습 방법에 대해 언급하신 글이 있었는데 재밌게 읽었던 기억이 납니다. 자세히는 기억이 나지 않습니다만, 로우 레벨을 무시하고 상위 레벨만 학습해서는 위험하는 글이었던 것 같습니다. 조엘 온 소프트웨어(1탄)에도 이와 비슷한 내용이 있었습니다. 추상화 레벨이 높은 것을 가지고 학습한다고 해도 학습 비용이 떨어지진 않는 다는 것이었습니다. 제대로 알려면 로우 레벨에 대한 학습이 필수이기 때문이라는 내용이었죠.

간단하게 말하자면, 자바 기초나 OO 기초없이 스프링만 공부한다고 나아지진 않는다는 거죠.(이런 글을 적는 제 자신은 오늘 String에 있는 trim() 메소드가 상상한대로 동작하지 않아서 좀 기분이 안 좋습니다.) Anyway, 전 그냥 큐브 맞추다 보니 이런 생각이 들었습니다.

따라하기는 쉬운데

잘 하기는 어렵고

창의적으로 하는 건 정말 어렵군.

요즘 가장 즐겨하는 일을 꼽자면, 큐브 맞추기와 TDD입니다. 하루의 절반은 TDD 연습 하는데 소비합니다.(얼마 되지도 않았습니다.ㅋㅋ)

– 큐브는 위에서도 말씀드렸지만, 30분만 인터넷에 검색해서 따라하면 맞출 수 있습니다.
– TDD도 ‘테스트 주도 개발’책에 나와있는 예제 보면서 똑같이 코딩하는 건 쉽습니다.(책에 나온 코드가 잘못 나와있으면 그 일도 별로 쉽지는 않지만 말이죠.)

– 큐브를 매뉴얼 없이 맞추려면 공식을 달달 외워야 하고, 패턴도 알아 두어야 합니다.
– TDD도 책 없이 하려면, TDD 개발 주기(Task 메모 -> 테스트 작성 -> 테스트 -> 구현 -> 테스트 -> 리팩터링 -> 테스트 -> Task 완료), 테스트 케이스 작성법, private 멤버 테스트 방법(Junit Recipe에 있는데 아직 못 봤습니다.), 예외 발생 확인 방법등을 알아 두어야 합니다.

– 큐브를 한 번에 한 칸만 맞추는게 아니라, 한 번에 여러 칸을 동시에 맞추는 공식을 개발하려면 굉장히 창의 적이어야 하고, 큐브를 통달하고 있어야 합니다. 보통 실력으론 어림없겠죠.
– TDD를 잘 하려면, 지례짐작을 하면 안 됩니다. 오직 테스트와 리팩터링을 통해서 매~우 자연스럽게 패턴이 도출되고 설계가 정제되는 경지에 이르게 될텐데. 역시 보통 수련과 실력으론 어렵습니다. 리팩터링도 잘 알고 있어야 하고 패턴도 잘 알고 있어야 하지만, 거기에 얽매이지 않은 이상한 경지에 다다라야 가능할 것 같습니다.

참으로 비슷하지 않나요. 모든 일이 다 그런가;;

An Ever So Slight Feeling of Dèjà Vu

1. Nested classes

– Java의 inner9(non static) class와 같은 개념은 C#에 없지만 static nested class 와 같은 것은 있다.
– 따라서 안쪽 클래스에서 감싸고 있는 클래스의 static 멤버에만 접근할 수 있다.

public class Car
{
    private Engine engine;

    private static string name = “람보르기니”;

    private class Engine
    {
        string make;

        public static void Main()
        {
            Console.WriteLine(name);
        }
    }
}

– Java에서는 anonymous inner class로 method 안에 클래스를 정의할 수 있는데, C#에서는 안 된다.

2. Threads and Volatile Members

– System.Threading.Thread 객체를 만들어서 System.Threading.ThreadStart 객체를 전달한다.
– Delegates를 사용하기 때문에, 어떤 메소드든 멀티쓰레드로 실행할 수 있다.
– System.Threading.Monitor 클래스의 Wait(), Pulse(), PulseAll()와 Thread.Sleep()로 쓰레드를 제어한다.

Thread t = new Thread(new ThreadStart(wt.PerformTask));
t.Start();

– C# and Java have the concept of the volatile keyword which is used to tell the language runtime that reordering instructions related to accessing such fields is prohibited.(어렵다. volatile)
– Java에서 더블 체크드 롹킹 안 되는 이유
    1. Currently the Java Memory Model does not
prevent reordering of writes to volatile variables with writes
to other variables so it is possible that the new object is
constructed before the helper reference is made to point at the
newly created object meaning that two objects are created.(이건 몰랐는데 복잡하네..)
    2. Also
it is possible that the helper reference is made to point at a
block of memory while the object is still being created meaning
that a reference to an incomplete object will be returned.
– C#에서의 volatile은 저런 문제를 막아 준다.(왜냐면, reads and writes cannot be
moved backward or forward across a volatile write.)
– C#,
being marked as volatile also prevents the Just In
Time compiler from placing the variable in a register and also
ensures that the variable is stored in global memory on
multiprocessor systems.
=> Anyway, C#에서는 volatile을 사용해서 더블 체크드 롹킹을 사용할 수 있다.

3. Operator Overloading

– 쌩뚱맞게 쓰면 안 된다. 직관적으로Intuitively 이해할수 있을 만한 경우에 사용하는 것이 좋다.
– C++과는 다르게 new, ( ),  ||, &&, = 나 +=, -=, 같은 복합 타입을 재정의 할 수는 없다. 그러나.. 재정의 된 연산자를 복합하여 사용할 수는 있다. 예를 들어, + 를 재정의 한 다음에 += 을 사용한다는 식의..

4. switch Statment

– C#에서는 string 타입도 지원한다.
– statement를 아예 한 줄도 적지 않으면, fall throght 하는데, 그렇지 않을 경우 무조건 beak; 문을 추가해야 함.(안그러면 컴파일 에러)

5. Assemblies

– .Net 프레임워크에서 코드 패키징 하는 유닛이다. Java의 JAR랑 비슷.
– 어샘블리는 EXE나 DDL 형태로 저장된다.

6. Collections

– System.Collections 네임스페이스에서 IList, IEnumerable, IDictionary, ICollection 과 CollectionBase 같은 인터페이스와 이들의 구현체로 ArrayList, Stack, Queue, HashTable 과 SortedList를 제공한다.
– System.Collections.Generic 네임스페이스에는 List<T>, Stack<T>,Queue<T>, Dictionary<K,T> 와SortedDictionary<K,T> 같은 제네릭 타입을 제공한다.

7. goto (no longer considered harmful)

– 가독성을 높이고 코드 중복을 줄이기 위해 사용한다.
– secondary usage of the goto
statement is the ability to mimic resumeable exceptions like
those in Smalltalk(???)

8. Virtual Methods (and final ones too)

– 자바의 기본적으로 모든 메소드는 virual method로써, 재정의가 가능하다. 단, final을 붙이면 재정의 할 수 없다. 같은 시그너처를 가진 메소드를 하위 클래스에 정의할 수 없다.
– C#에서는 virtual 키워드를 사용해서 재정의 할 수 있는 메소드를 상위 클래스에 정의 할 수 있다. 그리고 하위 클래스에서는 override 키워드를 사용해서 재정의 한다. 이렇게 해야만 다형성이 적용된다.
– C#에서는 virtual 키워드를 붙이지 않으면, 모두 final 메소드 처럼 동작하지만, 같은 시그너처를 가진 메소드를 정의할 수 있다. 다형성은 적용되지 않는다. 또는 new 키워드를 하위 클래스의 메소드에 붙여준다.

9. File I/O

using System;
using System.IO;

public class FileIOTest {

    public static void Main(string[] args){

    FileStream inputFile  = new FileStream(“input.txt”, FileMode.Open);
    FileStream outputFile = new FileStream(“output.txt”, FileMode.Open);

        StreamReader sr     = new StreamReader(inputFile);
        StreamWriter sw     = new StreamWriter(outputFile);

    String str;

    while((str = sr.ReadLine())!= null)
        sw.Write(str);

        sr.Close();
        sw.Close();
    }

}//FileIOTest

– 한글은 깨지던데, 역시 한글은 어려워..인코딩 신경써야 함.

10. Object Serialization

– C#에서는 직렬화를 XML 형태로도 할 수 있다. 바이너리 형태도 가능. 커스텀 방식을 사용할 수 도 있다.
– Java의 Serializable 인터페이스 ->  C#의 [Serializable]
– Java의 transient -> C#의 [NonSerialized]

11. Documentation Generation from Source Code Comments

– html 문서가 아니라 XML 문서를 만들어 준다. javadoc 같이 주석에 적어둔 XML을 HTML로 만들어 주는 툴은 없다.

///<summary>Calculates the square of a number.</summary>
///<param name=”num”>The number to calculate.</param>
///<return>The square of the number. </return>
///<exception>NumberTooBigException – this occurs if the square of the number
///is too big to be stored in an int. </exception>
 public static int square(int num){}

12. Multiple Classes in a Single File

– 파일 하나에 public class가 여러 개여도 상관없으며, 파일 이름과 클래스 이름이 달라도 상관없음.

13. Importing Libraries

– using 키워드 사용하기
– /r 로 컴파일러한테 Assembly 위치 알려주기.

14. Events

– C#은 delegate 키워드 를 사용한다.
– 이벤트는  System.EventArgs 를 상속한 클래스. 이 클래스는 독립적으로 생성할 수 있는 생성자를 가지고 있다. 그래서 new YourEventArgs(inits) 이런 형태로 넘겨질 수 있어야 한다.
– 퍼블리셔는 On 으로 시작하는 protected 메소드를 가지고 있다. 이 메소드들은 특정 이벤트가 발생할 때에 자동으로 호출 된다. 그럼 이 녀석은 발생한 지점 source와 이벤트 EventArgs 객체를 delegate를 호출하면서 넘겨준다.
– 구독자는 이벤트 델리게이트와 동일한 리턴 타입과 아규먼트를 가지고 있는 메소드다.
– 이벤트 델리케이트는 보통 void 타입의 리턴 타입이고, 아규먼트는 두 개를 가지고 있다. 한 개는 소스, 한 개는 EventArgs.
– “event” is used to automatically specify that a field within a subscriber is a delegate that will be used as a callback during an event-driven situation.
– +=, -= 을 컴파일러가 핸들러로 추가 삭제 하는 것으로 인식해준다.

        public delegate void EvenNumberSeenHandler(object sende, EventArgs e);  // 1

        public event EvenNumberSeenHandler EvenNumHandler; // 2

        protected void OnEvenNumberSeen(int num) // 3
        {
            if (EvenNumHandler != null)
                EvenNumHandler(this, new EvenNumberEvent(num));
        }

1. delegate 타입 설정. delegate가 가져야 할 메소드 인자 타입을 정의 => 어떤 타입의 이벤트를 처리할 지 정의.
2. 이벤트 핸들러 설정. => 이벤트가 발생할 때, 호출할 핸들러들을 정의 => 핸들러의 타입은 위에서 정의한 delegate 타입을 사용.
3. 이벤트 발생 시키기. => 위에 정의한 핸들러를 필요한 인자들과 함께 호출해주기.

pub.EvenNumHandler += new Publisher.EvenNumberSeenHandler(EventHandler2);
pub.RunNumbers();
pub.EvenNumHandler -= new Publisher.EvenNumberSeenHandler(EventHandler);

– 아 복잡하다.

15. Cross Language Interoperability

– Java는 Java Native Interface를 사용해서  C나 C++ 어샘블리를 사용할 수 있다.
– C#은 CRL을 사용해서 다른 언어를 사용할 수 있다.
– COM 객체를 C#에서 사용할 수 있다. 반대도 가능.
– C# programs can also call almost any function in any DLL using a combination of the extern keyword and the DllImport attribute on the method declaration.

– 역시 복잡하다.