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 타입으로 형변환 해버릴 수 있다. 그런 다음에 찍으면 숫자가 찍힌다.