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
,