C# 열거형(enum)

C# 2016. 6. 20. 21:40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
enum Days1
{
    Sunday,
    Monday = 5,
    Tuesday
}
[Flags]
enum Days2
{
    Sunday,
    Monday,
    Tuesday
}
static void Main(string[] args)
{
    Days1 workingDays = Days1.Monday | Days1.Tuesday;
    Console.WriteLine(workingDays.HasFlag(Days1.Tuesday));
    Console.WriteLine(workingDays);
 
    Days2 workingDays2 = Days2.Monday | Days2.Tuesday;
    Console.WriteLine(workingDays2.HasFlag(Days2.Sunday));
    Console.WriteLine(workingDays2);
}
cs

실행 결과 :

True

7

True

Monday, Tuesday



C#에서도 enum을 사용할 수 있다.

[Flags] attribute를 달아줬을 때와 달아주지 않았을 때

|(or) 연산자를 먹인 후 ToString()이 다르게 작동하는 부분을 예제에서 확인할 수 있다.

'C#' 카테고리의 다른 글

C# ref 키워드, out 키워드  (0) 2016.06.20
C# 구조체와 클래스 선택 기준  (0) 2016.06.10
C# 값 타입의 new 할당  (0) 2016.06.10
C# 인터페이스 - IEnumerable, IEnumerator 인터페이스  (0) 2016.06.09
C# 인터페이스(interface)  (0) 2016.06.09
Posted by RPG만들기XP
,

C# ref 키워드, out 키워드

C# 2016. 6. 20. 15:22
1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    Program program = new Program();
    int a = new int();
    Func1(ref a);
    Console.WriteLine(a);
}
static void Func1(ref int x)
{
    x = x + 1;
}
cs

실행 결과 : 

1


value type를 call by reference로 넘길 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Point
{
    public int x;
    public int y;
}
static void Main(string[] args)
{
    Point pt = null;
 
    Func1(pt);
    Console.WriteLine("pt : " + pt);
 
    Func2(ref pt);
    Console.WriteLine("pt.x : " + pt.x + " pt.y : " + pt.y);
}
static void Func1(Point pt)
{
    pt = new Point();
    pt.x = 1;
    pt.y = 2;
}
static void Func2(ref Point pt)
{
    pt = new Point();
    pt.x = 3;
    pt.y = 4;
}
cs

실행 결과 : 

pt : 

pt.x : 3 pt.y : 4


얕은 복사(Func1)와 ref에 의한 전달(Func2)의 차이를 잘 보여주는 예제이다.

얕은 복사에 의한 매개변수는 단순히 주소값을 복사해서 넘기는 것이며, Main에서의 pt와 Func1에서의 pt는 같은 주소를 가리키는 서로 다른 포인터이다.

하지만 Func2의 pt는 Main에서의 pt와 같다.




out 키워드 또한 ref 키워드처럼 사용하여 참조에 의한 호출을 가능케 한다.

차이점은

  1. out으로 지정된 인자에 넘길 변수는 초기화되지 않아도 된다.
    초기화되어 있더라도 out 인자를 받는 메서드에서는 그 값을 사용할 수 없다.
  2. out으로 지정된 인자를 받는 메서드는 반드시 변수에 값을 넣어서 반환해야 한다.
C언어 함수에서 인자로 주소값을 받아서 결과를 담아 돌려주는 방식과 같다.
딱 그 용도로만 쓸 수 있도록 만들어놓은 키워드이다.


'C#' 카테고리의 다른 글

C# 열거형(enum)  (0) 2016.06.20
C# 구조체와 클래스 선택 기준  (0) 2016.06.10
C# 값 타입의 new 할당  (0) 2016.06.10
C# 인터페이스 - IEnumerable, IEnumerator 인터페이스  (0) 2016.06.09
C# 인터페이스(interface)  (0) 2016.06.09
Posted by RPG만들기XP
,

1. 별 상관 없을 경우 모두 클래스로 구현한다.

2. 깊은/얕은 복사의 차이가 민감한 타입일 경우 선택적으로 구조체로 구현한다.

3. 참조 타입은 GC에 부담이 되므로 GC에 부하를 주는 것을 피해야 할 경우 구조체로 구현한다.

'C#' 카테고리의 다른 글

C# 열거형(enum)  (0) 2016.06.20
C# ref 키워드, out 키워드  (0) 2016.06.20
C# 값 타입의 new 할당  (0) 2016.06.10
C# 인터페이스 - IEnumerable, IEnumerator 인터페이스  (0) 2016.06.09
C# 인터페이스(interface)  (0) 2016.06.09
Posted by RPG만들기XP
,

C# 값 타입의 new 할당

C# 2016. 6. 10. 18:05
1
2
int a;
Console.WriteLine(a); // 컴파일 안됨
cs


초기화하지 않은 인스턴스를 사용시 컴파일 에러를 발생시킨다.


1
2
int a = new int();
Console.WriteLine(a); // 컴파일 안됨
cs


실행 결과 : 0


값 형식의 변수를 new로 생성하면 해당 변수의 모든 값을 0으로 할당한다.

이는 struct에도 마찬가지.

Posted by RPG만들기XP
,
1
2
3
4
5
6
7
8
9
10
11
public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
 
public interface IEnumerator
{
    object Current{ get; }
    bool MoveNext();
    void Reset();
}
cs


C++의 iterator라고 생각할 수 있다.


IEnumerable 인터페이스를 컨테이너 클래스에서 구현하고,

iterator 클래스에서 IEnumerator 인터페이스를 구현하여 foreach(object elem in container)문을 사용할 수 있다.

'C#' 카테고리의 다른 글

C# 구조체와 클래스 선택 기준  (0) 2016.06.10
C# 값 타입의 new 할당  (0) 2016.06.10
C# 인터페이스(interface)  (0) 2016.06.09
C# 델리게이트(delegate)  (0) 2016.06.08
C# 추상 클래스  (0) 2016.06.08
Posted by RPG만들기XP
,

C# 인터페이스(interface)

C# 2016. 6. 9. 21:06
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyClass : Clickable
{
 
    public void Clicked() // override 키워드가 필요없다.
    {
 
    }
}
public class MyClass2 : Clickable
{
    void Clickable.Clicked() // 이렇게도 됨
    {
    }
}
public interface Clickable
{
    void Clicked();
}
cs


C#에서는 다중 상속을 지원하지 않는 대신 인터페이스를 쓸 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyClass2 : Clickable
{
    int a;
    void Clickable.Clicked() // 이렇게도 됨
    {
    }
    int Clickable.Member { get; set; }
    public int Member2
    {
        set { a = value; }
    }
}
public interface Clickable
{
 
    int Member { get; set; } // 프로퍼티도 된다.
    int Member2 { set; }
    void Clicked();
}
cs


프로퍼티도 된다.

'C#' 카테고리의 다른 글

C# 값 타입의 new 할당  (0) 2016.06.10
C# 인터페이스 - IEnumerable, IEnumerator 인터페이스  (0) 2016.06.09
C# 델리게이트(delegate)  (0) 2016.06.08
C# 추상 클래스  (0) 2016.06.08
C# 연산자 오버로딩  (0) 2016.06.08
Posted by RPG만들기XP
,

C# 델리게이트(delegate)

C# 2016. 6. 8. 16:53
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Program
{
    delegate void FuncDelegate();
    static void Main(string[] args)
    {
        Program program = new Program();
        FuncDelegate fooFunc = new FuncDelegate(program.foo);
        FuncDelegate fooFunc2 = program.foo;
        fooFunc();
        fooFunc2();
    }
 
    void foo()
    {
        Console.WriteLine("Hello, World!");
    }
}
cs


실행 결과:

Hello, World!

Hello, World!


C++에서의 std::function처럼 사용할 수 있다.


C# 1.0에서는 FuncDelegate fooFunc = new FuncDelegate(program.foo); 형태로 다소 복잡하게 사용하여야 했지만,

C# 2.0부터는 FuncDelegate fooFunc2 = program.foo; 형태로 쉽게 사용할 수 있다.

따라서 7,8번 라인은 동일한 역할을 수행하며, 9,10번 라인도 동일한 역할을 수행한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Program
{
    static void Main(string[] args)
    {
        Program program = new Program();
        System.Func<intint> fooFunc = program.foo;
        System.Func<intboolstring> fooFunc2 = program.foo2;
 
        System.Console.WriteLine(fooFunc(3));
        System.Console.WriteLine(fooFunc2(3false));
    }
 
    int foo(int var)
    {
        return 2 * var;
    }
    string foo2(int var1, bool var2)
    {
        return var1.ToString() + var2.ToString();
    }
}
cs


실행 결과 : 

6

3False


System.Func<>를 이용하면 더 편리하게 사용할 수 있다.

하지만 반환값이 void인 메소드는 System.Func<>를 이용할 수 없다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Program
{
    static void Main(string[] args)
    {
        Program program = new Program();
        System.Func<intint> fooFunc = program.foo;
        System.Func<intboolstring> fooFunc2 = program.foo2;
 
        System.Console.WriteLine(fooFunc(3));
        System.Console.WriteLine(fooFunc2(3false));
        fooFunc2 += program.foo3;
        System.Console.WriteLine(fooFunc2(3false));
    }
 
    int foo(int var)
    {
        return 2 * var;
    }
    string foo2(int var1, bool var2)
    {
        return var1.ToString() + var2.ToString();
    }
    string foo3(int var1, bool var2)
    {
        return var1.ToString() + var2.ToString() + "here is foo3";
    }
}
cs


실행 결과 :

6

3False

3Falsehere is foo3


여러 메소드를 조합해서 하나의 delegate로 만들 수도 있다.

내부적으로 Combine()을 이용해 동작하며, 조합한 순서대로 호출 순서가 보장된다.

'C#' 카테고리의 다른 글

C# 인터페이스 - IEnumerable, IEnumerator 인터페이스  (0) 2016.06.09
C# 인터페이스(interface)  (0) 2016.06.09
C# 추상 클래스  (0) 2016.06.08
C# 연산자 오버로딩  (0) 2016.06.08
C# 클래스 - Object 클래스  (0) 2016.06.08
Posted by RPG만들기XP
,

C# 추상 클래스

C# 2016. 6. 8. 03:04
1
public abstract void Foo();
cs


C#에서 abstract 키워드를 붙이면(virtual 키워드는 생략)


1
virtual void Foo() = 0;
cs

C++에서의 위 구문과 같다.


순수 가상함수(C#에서는 추상 메소드라고 하는 것 같다.)를 가지는 클래스는 자연히 추상 클래스가 된다.

'C#' 카테고리의 다른 글

C# 인터페이스(interface)  (0) 2016.06.09
C# 델리게이트(delegate)  (0) 2016.06.08
C# 연산자 오버로딩  (0) 2016.06.08
C# 클래스 - Object 클래스  (0) 2016.06.08
C# 클래스 - 상속  (0) 2016.06.08
Posted by RPG만들기XP
,

C# 연산자 오버로딩

C# 2016. 6. 8. 03:00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Program
{
    static void Main(string[] args)
    {
        MyClass inst1 = new MyClass(1);
        MyClass inst2 = new MyClass(3);
        MyClass inst3 = inst1 + inst2;
        Console.WriteLine(inst3);
    }
}
public class MyClass
{
    int value;
 
    public override string ToString()
    {
        return value.ToString();
    }
 
    public MyClass(int value)
    {
        this.value = value;
    }
    public MyClass() : this(0)
    {
    }
 
    public static MyClass operator +(MyClass left, MyClass right)
    {
        return new MyClass(left.value + right.value);
    }
}
cs


실행결과 : 4


아주 잘된다.



배열 인덱스 연산자 []는 오버로드 할 수 없지만, C#에서는 이를 대체하는 별도의 인덱서 구문을 지원한다.

추후 정리.


형변환 연산자 (type)x 또한 오버로드할 수 없지만, explicit, implicit를 이용해 대체 정의가 가능하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Program
{
    static void Main(string[] args)
    {
        Gram gram = new Gram(2000);
        KilloGram kg = new KilloGram(3);
 
        // Gram wrongGram = new KilloGram(3); // 빌드 안됨. explicit은 명시적 캐스팅만 허용
        KilloGram kgFromGram = gram; // 잘됨
        // Gram gramFromKg = kg; // 당연히 안됨
        Gram gramForKg = (Gram)kg;
 
        Console.WriteLine(gram);
        Console.WriteLine(kg);
        Console.WriteLine(kgFromGram);
        Console.WriteLine(gramForKg);
    }
}
public class Weight
{
    decimal value;
    public decimal Value { get { return value; } }
 
    public Weight(decimal value)
    {
        this.value = value;
    }
}
 
public class Gram : Weight
{
    public Gram(decimal value) : base(value) { }
 
    public override string ToString()
    {
        return Value + "g";
    }
 
    static public implicit operator KilloGram(Gram gram)
    {
        return new KilloGram(gram.Value / 1000m);
    }
}
 
public class KilloGram : Weight
{
    public KilloGram(decimal value) : base(value) { }
 
    public override string ToString()
    {
        return Value + "kg";
    }
 
    static public explicit operator Gram(KilloGram kg)
    {
        return new Gram(kg.Value * 1000m);
    }
}
cs


출력 결과 : 

2000g

3kg

2kg

3000g


형 변환 연산자 오버로딩 예시이다.

implicit은 암시적 형변환을 허용하고,
explicit은 형변환 연산자를 사용할 때만 형변환을 해준다.


'C#' 카테고리의 다른 글

C# 델리게이트(delegate)  (0) 2016.06.08
C# 추상 클래스  (0) 2016.06.08
C# 클래스 - Object 클래스  (0) 2016.06.08
C# 클래스 - 상속  (0) 2016.06.08
C# 클래스 - 형변환  (0) 2016.06.08
Posted by RPG만들기XP
,

C#의 모든 클래스의 최상위에 있는 클래스이다.
따라서 사용자 정의 클래스를 비롯한 모든 클래스는 Object를 상속받는다.
Object 클래스는 다음과 같은 4개의 public 메소드를 포함하고 있다.

1
2
3
4
5
6
7
public class object
{
    public virtual bool         Equals(object obj);
    public virtual int         GetHashCode();
    public Type                 GetType();
    public virtual string     ToString;
}
cs



1
2
3
4
5
6
7
8
9
10
11
namespace CSharp_Practice
{
    class Program
    {
        static void Main(string[] args)
        {
            Program program = new Program();
            Console.WriteLine(program.ToString());
        }
    }
}
cs

실행 결과 : CSharp_Practice.Program


ToString() 메소드는 기본적으로 해당 인스턴스가 속한 클래스의 전체 이름(FQDN)을 반환한다.

하지만 각 클래스에서 오버라이드 할 수 있기 때문에, 다르게 동작할 수도 있다.

값 타입들(short, int, ... )의 ToString()은 담고 있는 값을 반환한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Parent
{
    public void foo()
    {
        System.Console.WriteLine("Foo!");
    }
}
 
Parent parent = new Parent();
Type type = parent.GetType();
 
Console.WriteLine(type.FullName);
Console.WriteLine(type.IsClass);
Console.WriteLine(type.IsArray);
cs


실행 결과 : 

Parent

True

False


GetType() 메소드는 인스턴스에서 타입을 알아낸다.


*클래스명에서 바로 타입을 얻어내고 싶을 때는 typeof 메소드를 이용한다.

ex) Type type = typeof(Parent);



Equalse(object) 메소드는 인자와 인스턴스가 같은지 비교해 bool형으로 반환한다.

value type에 대해서는 값으로 비교, ref type에 대해서는 같은 주소를 가리키고 있는지를 비교한다.



GetHashCode() 메소드는 특정 인스턴스를 고유하게 식별할 수 있는 4바이트 int값을 반환한다.

Equals()가 true를 반환할 경우 두 객체의 HashCode도 같아야 한다.

때문에 보통 Equals 메소드를 하위 클래스에서 재정의할 때 GetHashCode까지 재정의해야 한다.

당연히 value type의 경우 값이 같다면 HashCode또한 같다.

'C#' 카테고리의 다른 글

C# 추상 클래스  (0) 2016.06.08
C# 연산자 오버로딩  (0) 2016.06.08
C# 클래스 - 상속  (0) 2016.06.08
C# 클래스 - 형변환  (0) 2016.06.08
C# 클래스 - 프로퍼티(property)  (0) 2016.06.07
Posted by RPG만들기XP
,