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 경계 밖에 있는 녀석들을 받아오면 안 된다.

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.

– 역시 복잡하다.

The Same But Different

1. Main Method

– Java와 C# 모두 메인 메소드가 진입점이다.
– C#의 메소드 작명 지침에 따라 Main 메소드 이름이 M 대문자로 시작한다.
– C#의 Main 메소드는 인자로 아무것도 안 가질 수 있다.

public static void Main() {}

– C#에서는 실행 파일 만들 때, /main 옵셥을 사용해서 집입점을 선택할 수 있다.
– 실행 파일의 이름이 소스 파일 이름과 달라도 되네.. 거의 Java의 JAR파일이랑 EXE랑 비슷하네..

사용자 삽입 이미지
2. Inheritance Syntax

– Java 처럼 상속은 extends, 인터페이스 구현은 implements 로 구분하지 않는다.
– 그냥 : 로 둘 다 나타낸다. 대신 인터페이스는 .Net 작명 지침 상 대문자 I를 클래스 이름 맨 앞에 붙여주니까, 인터페이스 구현인지 상속인지 구분 할 수 있다.

3. Run Time Type Identification (is operator)

– Java의 instanceof 연산자는 C#에서 is(짧아서 좋네.)

  if(x is MyClass)
   MyClass mc = (MyClass) x;

4. Namespaces

– Java의 package 이름은 물리적인 폴더 구조와 일치 해야 한다.
– C#의 namespace는 논리적인 구조를 나타내며, namespace안에 namespace를 추가할 수 있다.

    namespace Whiteship
    {
        public class A { }
        public class B { }

        namespace Sun
        {
            public class A { }
            public class B { }
        }
    }

5. Constructors, Destructors and Finalizers

– C#의 생성자는 Java의 생성자와 모양과 뜻이 같다.
– C#의 Destructor는 C++ 문법을 사용하지만 뜻은 Java와 더 비슷하다.(GC를 명시적으로 호출하지 않기 때문에 언제 호출 될지 예측할 수 없기 때문인가?)
– C#의 Destructor는 클래스 이름 앞에 ~를 붙인다.
– In C#, destructors(finalizers) automatically call the base class finalizer after executing which is not the case in Java.(???)

6. Synchronizing Methods and Code Blocks

– Java의 synchronized 블럭과 동일한 것을 C#에서는 lock 키워드를 사용한다.
– 동기화 메소드는 Java에서 synchronized 키워드를 메소드 이름 앞에 붙여주는데, C#에서는 [MethodImpl(MethodImplOptions.Synchronized)] 애노테이션을 붙인다.
– using System.Runtime.CompilerServices; 붙여 줘야 함.

7. Access Modifiers

– (참조 한 곳에서 Java의 접근 지시자를 잘못알고 있는 듯..)
– C#의 public은 Java의 public
– C#의 private은 Java의 private
– C#의 protected는 Java의 protected(상속 받은 클래스들에서 참조 가능)

– C#의 default는 private 이지만, Java의 default는 default(같은 패키지에서만 참조 가능)
– C#의 internal은 같은 assmbly에서만 참조 가능.
– C#의 internal protected는 같은 자기 자신과 assembly와 상속받은 클래스에서 참조 가능.

8. Reflection

– C# is done at the
assembly
level while reflection in Java is done at the
class level.
– C#은 타겟 클래스를 담고 있는 DLL 파일이 필요해.
– Java의 Class는 C#의 Type

Type type = typeOf(MyClass);

– 동적으로 생성되는 타입은 어떻게 알아내지?

ICollection a = new ArrayList();
Type type = typeOf(a); //이런건 안되던데;;

9. Declaring Constants

– Java는 컴파일 시점에 설정거나 실행중에 설정할 상수 모두를 final로 나타낸다.
– C#에서 컴파일 시점에 설정할 상수는 const 키워드를 사용하고 실행 중에 설정할 상수는 readonly  키워드를 사용한다.
– primitive 타입 상수와 reference 타입 상수에 대한 개념은 Java와 동일하다.
– Java에서는 메소드의 파라미터도 final을 붙일 수 있는데 C#에서는 그런 기능이 없다.(그럼 C#은 inner class에 참조 할 때 final 안붙여도 상관없나..)

10. Primitive Types

– Java의 byte 는 C#에서 sbyte
– C#에서는 unsigned 타입을 제공한다. uint, ulong, ushort, byte
– C#에서는 decimal 타입을 제공한다. 더 정확하고 더 많은 공간과 시간을 소비한다. 값뒤에 d를 붙여준다.

11. Array Declarations

– C#에서는 다음과 같은 문법으로만 배열을 생성할 수 있다.
int[] iArray = new int[100];
– Java에서는 아래처럼 해도 되지만, C#에서는 안 된다.
float fArray[] = new float[100];

12. Calling Base Class Constructors and Constructor Chaining

– Java와 마찬가지로 상위 클래스의 생성자 호출은 제일 먼저 실행되어야 한다.(그래야 초기화 되지 않은 변수를 가져다 쓰는 일이 벌어지지 않을테니까..)
– 생성자 안에서 자기가 가지고 있는 다른 생성자를 호출하는 것을 Constructor Chaining 이라고 한다.
– 생성자 바디에 넣는게 아니라 아예 메소드 시그너쳐 바로 옆에 붙여주는 군..

MyException(string message): this(message, null){}
MyException(string message, Exception innerException): base(message, innerException){}

13. Variable Length Parameter Lists

– 가변인자를 Java에서는 … 을 사용해서 여러개의 파라미터를 배열에 받아 올 수 있다.
– C#에서는 params 키워드를 사용하며 배열 타잎 앞에 붙여준다.

public void printTitleAndNums(string title, params int[] nums){}

14. Generics

– Although similar in concept to templates in C++, the Generics feature in C# and Java is not implemented similarly

– Java는 type erasure(컴파일 이후에는 Generic을 삭제하고 Object 타입으로 동작한다. 알아서 해당 타입으로 캐스팅 해준다.)를 사용해서 generic 기능을 구현했다.
– 기존 코드legacy code와의 호환interoperability 때문에 이렇게 구현했다.
    –  런타임 시에 타입을 알 수 없다는 단점이 있다. 리플랙션으로 알아낼 수가 없다.
    – 항상 객체 타입이어야 한다. 따라서 정수형이 필요할 때, Collection<int>가 아니라 Collection<Integer>를 사용해야 한다.

– C#은 .NET 런타임의 Instruction Language(IL)의 지원을 받는다. Generic 타입이 컴파일 되면, 만들어진 IL이 특정 타입에 대한 Placeholder를 가지고 있다. Generic 타입에 대한 레퍼런스 초기화 요청이 오면 Placeholder에 해당 타입이 있는지 확인하고 있으면, 그것을 돌려주고 없으면 Generic 타입 파라미터를 요청한 타입으로 바꿔준다. 이때 요청 받은 타입이 Reference 타입일 경우에는 Generic 타입 파라미터를 Object로 바꿔주지만, 해당 타입에 접근할 때 캐스팅을 하지는 않는다.(캐스팅 하지 않고도 해당 타입의 멤버에 접근할 수가 있나..??)
=> C#은 value 타입을 Generic 타입으로 사용할 수 있다.
=> C#은 런타임시에 Generic 타입을 알 수 있다.

– Java의 와일드카드 타입 ? 은 C#의 generic type inferencing

– C#와 Java 모두 Generic 타입에 제약을 가할 수 있다.
    – derivation constraint: 하위 제한으로 특정 인터페이스나 클래스를 구현하거나 상속받은 클래스로 제한하기
    – default constructor constraint:  public 기본 생성자를 가진 클래스로 제한
    – reference/value type constraint constrains: Generic 타입 파라미터를 reference나 value 타입으로 제한.

– C#은 default 연산자를 제공한다. reference 타입은 null, value 타입은 0과 공백을 리턴한다.

15. for-each Loop

– 배열이나 System.Collections.IEnumerable를 구현한 클래스 타입을 간단하게 순회할 수 있다.
– C#에서는 foreach  와 in을 사용한다.

foreach(int num in nums)
Console.WriteLine(num);

16. Metadata Annotations

– [MethodImpl(MethodImplOptions.Synchronized)]: 동시에 여러 쓰레드가 해당 메소드를 사용하는 것을 막기 위해서 사용.
– [Serializable]: Java의 Serializable 인터페이스와 같은 효과.
– [FlagsAttribute]: 비트와이즈 연산을 지원해야 한드는 의미로, Enumerarion위에 붙여준다.
– [WebMethod]: ASP.NET에서 사용하는데, 이걸 메소드 위에 붙이면 자동으로 웹에서 웹 서비스로 사용할 수 있다.
– 리플랙션을 사용해서 모듈, 클래스, 메소드, 필드에 붙어있는 어트리뷰트에 접근하는 것이 가능하다.(자바도 가능)
– System.Attribute 클래스를 상속해서 원하는 어트리뷰트를 만들 수도 있다.

– Java는 Meta Annotation을 만들 수 있지만, C#은 못한다.

17. Enumerations

– Java의 Enum은 Type-Safe하고, 필드와 메소드를 추가할 수 있고, 인터페이스를 구현하는 것도 가능하다.
– C#에서는 그냥 int 값이다. 따라서 Type-Safe하지 못하다.
– Console.WriteLine()으로 찍으면 문자로 찍히는데.. int 값을 Enum 타입으로 형변환 해버릴 수 있다. 그런 다음에 찍으면 숫자가 찍힌다.

The More Things Change The More They Stay The Same

참조 : A COMPARISON OF MICROSOFT’S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS’ JAVA PROGRAMMING LANGUAGE

1. We Are All Objects

– java.lang.Object와 비슷한 클래스 System.Object
– 모든 클래스들의 슈퍼 클래스.
– 메소드 이름이 대문자로 시작하는 군.
– object 키워드 == System.Object

2. Keyword Jumble

– 자바에는 없는 키워드가 C#에는 많이 있군.
자바 -> C#
extends, implements -> :
boolean -> bool
final -> sealed
protected -> internal (C#의 protected는 다른 의미인듯..)

3. Of Virtual Machines and Language Runtimes

– 자바 소스 코드 -> 바이트 코드 -> Run in JVM
– C# 소스 코드 -> IL(Intermediated Language) -> Run in CLR(Common Language Runtime)

4. Heap Based Classes and Garbage Collection

– 자바는 new 키워드를 사용해서 모든 객체를 힙 영역에 생성.
– C#도 new 키워드를 사용해서 일부 클레스의 객체를 힙 영역에 생성.
– JVM 처럼 CLR도  Mark and Compact garbage collection algorithm 사용해서 Gabage Collection을 수행한다.
– value 타입은 stack에 생성할 수도 있나보다.

5. Arrays Can Be Jagged

– C나 C++의 다차원 배열에서 배열은 꼭 같은 길이의 배열을 가져야 했다.
– C#과 Java는 배열이 다른 길이의 배열을 가지고 있어도 된다.
int [][]myArray = new int[2][];
myArray[0] = new int[3];
myArray[1] = new int[9];

6. No Global Methods

– C++ 에서는 메소드가 클래스 밖에 있어도 됐나보다.
– C#은 자바처럼 메소드가 클래스의 멤버나 Static Method여야 한다.

7. Interfaces, Yes. Multiple Inheritance, No

– Java처럼 인터페이스는 다중 상속(구현)을 허용.
– Java처럼 상속은 다중 상속을 허용하지 않음.

8. Strings Are Immutable

– C#의 System.String은 Java의 java.lang.String과 비슷. 변하지 않는다.
– C#의 System.Text.StringBuilder는 Java의 java.lang.StringBuffer과 비슷.(동기화 시켜놓은 것도 비슷하려나;; 안했으면 StringBuilder랑 비슷한건데..)
– string 또는 String으로 표기할 수도 있다.

9. Unextendable Classes

– 자바에서 final 키워드를 class 앞에 붙이면 더이상 상속하지 못하는 클래스가 된다.
– C#에서는 sealed 키워드를 class 앞에 붙이면 된다.

10. Throwing and Catching Exceptions

– 자바와 동일하게 예외 클래스들의 최상위에 Exception 클래스를 제공한다.
– 예외를 감싸서 다시 던질 수 있다.

11. Member Initialization at Definition and Static Constructors

– 만약 멤버 변수가 인스턴스 변수이면, 생성자가 호출되기 전에 초기화 한다.
– Static 멤버들은 해당 멤버를 사용하기 전이나, 멤버가 속해있는 클래스의 객체를 만들기 조금 전에 초기화 한다.
– 인스턴스 변수를 생성하거나 Static 메소드를 호출하기 전에 특정 블럭을 실행하도록 하는 것도 가능하다.
– 자바에서는 이런 코드 블럭을 static 초기화 블럭이라고 한다.
– C#에서는 static 생성자라고 한다.(실제 모양도 생성자 모양.)

using System;

class StaticInitTest{

    string instMember = InitInstance();

    string staMember = InitStatic();
   

    StaticInitTest(){
    Console.WriteLine(“In instance constructor”);
    }

    static StaticInitTest(){
    Console.WriteLine(“In static constructor”);
    }

    static String InitInstance(){
    Console.WriteLine(“Initializing instance variable”);
    return “instance”;
    }

     static String InitStatic(){
    Console.WriteLine(“Initializing static variable”);
    return “static”;
    }

    static void DoStuff(){
    Console.WriteLine(“Invoking static DoStuff() method”);
    }

   
    public static void Main(string[] args){

    Console.WriteLine(“Beginning main()”);

    StaticInitTest.DoStuff();
   
    StaticInitTest sti = new StaticInitTest();

    Console.WriteLine(“Completed main()”);

    }

}

In static constructor
Beginning main()
Invoking static DoStuff() method
Initializing instance variable
Initializing static variable
In instance constructor
Completed main()

이런 코드가 나온이유.

main() 메소드 실행하기 전에, static 생성자가 호출 된다.

In static constructor

그 다음 static 메소드를 호출할 때는 이미 static 생성자가 호출 됐기 때문에 그냥 메소드 호출.

Invoking static DoStuff() method

생성자가 호출되기 전에 인스턴스 변수들을 초기화 하기 때문에, new StaticInitTest(); 하는 순간 필드들을 초기화 하려고 하겠지.. 그래서..

Initializing instance variable
Initializing static variable

12. Boxing

– .Net은 boxing, unboxing 그냥 된다.
– Java도 5 부터는 된다.
– C#에서도 Collection에는 객체만 들어갈 수 있군.