블로그 이미지
따시쿵

calendar

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

Notice

2015. 6. 8. 17:22 C#

람다식을 사용하는 이유와 목적을 먼저 살펴 보는게 순서일 듯 싶네요.

 

  • 익명 메소드를 만드는 경우
  • Func와 Action으로 더 간편하게 무명 함수 만드는 경우
  • LINQ를 이용한 방법으로 표현하는 경우
1. 익명 메소드(Anonymous method)를 만드는 경우

 

익명 메소드를 만드는 경우에는 delegate를 이용한 방법도 있습니다. 그런데 람다식을 이용한 방법도 제공하는 이유는 개발 히스토리에 해답이 있습니다.

 

마이크로소프트는 C# 2.0 에서 델리게이트를 이용한 익명 메소드를 만드는 방법을 제공했고, 람다식은 C# 3.0 에서 와서야 도입 되었습니다. 따라서 C# 2.0 에서 작성한 프로그램을 C# 3.0 에서 기능을 삭제할 수는 없는 일입니다.

 

식 형식

 

매개 변수 목록 => 식

 

문 형식

 

(매개 변수 목록) => {

                             ..........................

                             ..........................

                             ..........................

                           };

 

 

 

예제1 : 식 형식의 람다식 표현 

        delegate int Calculate(int a, int b);

        static void Main(string[] args)
        {
            // 1. 람다식을 이용한 표현(매개변수 타입 있는 경우)
            Calculate cal1 = (int a, int b) => a + b;
            Console.WriteLine("Lambda Expression : {0} + {1} = {2}", 4, 5, cal1(4, 5));

            // 2. 람다식을 이용한 표현(매개변수 타입 없는 경우)
            Calculate cal2 = (a, b) => a + b;
            Console.WriteLine("Lambda Expression : {0} + {1} = {2}", 4, 5, cal2(4, 5));

            // 3. 델리게이트를 이용한 표현
            Calculate cal3 = delegate(int a, int b) { return a + b; };
            Console.WriteLine("Delegate : {0} + {1} = {2}", 4, 5, cal3(4,5));

            Console.ReadLine();
        }

 

 

 

 

예제 2: 문 형식의 람다식

 

식 형식의 람다식에서는 반환 형식이 없는 무명 함수를 만들 수 없지만, 문 형식의 람다식을 이용하면 가능합니다.

        delegate void DoSomething();
        static void Main(string[] args)
        {
            DoSomething DoIt = () =>
            {
                Console.WriteLine("여기는 ");
                Console.WriteLine("대한민국 ");
                Console.WriteLine("입니다");
            };

            DoIt();

            Console.ReadLine();
        }

 

 

 

 

 

예제3 : 람다식이 익명 메소드를 대치하는 경우. 파라미터가 생략되는 경우가 있습니다.

 

 

button control 의 Click 이벤트는 EventHandler 델리게이트이며, 두 개의 파라미터를 가집니다. object sender, EventArgs e. 파라미터가 익명 메소드 안에서 사용하지 않는 경우에는 생략하는 경우도 있습니다.

        private void Form1_Load(object sender, EventArgs e)
        {
            Button button1 = new Button();
            button1.Text = "Click me !!!";

            // 1. 델리게이트 이용 & 파라미터를 생략한 경우
            button1.Click += delegate
            {
                MessageBox.Show("Button1 Clicked!");
            };

            // 2. 델리게이트 이용 & 파라미터가 있는 경우
            button1.Click += delegate(object eventSender, EventArgs eventArgs)
            {
                MessageBox.Show("Button1 Clicked!");
            };

            // 3. 람다식을 이용한 식으로 표현함
            button1.Click += (object eventSender, EventArgs eventArgs) => MessageBox.Show("Button1 Clicked!");

            // 4. 람다식을 이용한 문으로 표현함
            button1.Click += (object eventSender, EventArgs eventArgs) => { MessageBox.Show("Button1 Clicked!"); };

            // 5. 람다식 이용 & 파라미터 타입 생략하는 경우
            button1.Click += (eventSender, eventArgs) => { MessageBox.Show("Button1 Clicked!"); };

            this.Controls.Add(button1);
        }

 

 

 

 

 

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

람다식(Lambda Expression) - 3  (0) 2015.06.09
람다식(Lambda Expression) - 2  (0) 2015.06.09
EventHandler 와 EventHandler<TEventArgs> Delegate  (0) 2015.06.04
Event 와 Delegate  (0) 2015.06.01
초단위 시간 경과 보이기  (0) 2015.05.12
posted by 따시쿵
2015. 6. 4. 12:10 C#

프로그램 설명


EventHandler 와 EventHandler<TEventArgs> Delegate 를 비교하여 설명하는 예제입니다.

  • EventHandler Delegate  - 이벤트 데이터가 없는 이벤트를 처리할 메서드를 나타냅니다.
  • EventHandler<TEventArgs> Delegate - 이벤트가 데이터를 제공할 때 이벤트를 처리할 메서드를 나타냅니다.

1. EventHandler delegate


구문


[SerializableAttribute]

[ComVisibleAttribute(true)]

public delegate void EventHandler(

Object sender,

EventArgs e

)



매개 변수


sender

형식: System.Object

이벤트 소스입니다. 


e

형식: System.EventArgs

이벤트 데이터가 포함되지 않은 개체입니다. 


설명


.NET Framework의 이벤트 모델은 이벤트와 이벤트 처리기를 연결하는 이벤트 대리자가 있다는 사실을 기초로 만들어졌습니다. 이벤트를 발생시키려면 다음과 같은 두 가지 요소가 필요합니다.


  • 이벤트에 응답하는 메서드를 식별하는 대리자입니다.
  • 이벤트 데이터를 제공 하는 경우 이벤트 데이터를 보유하 고 필요한 경우는 클래스입니다.


대리자는 시그니처를 정의하는 형식, 즉 메서드에 대한 반환 값 형식과 매개 변수 목록 형식입니다. 대리자 형식을 사용하여 대리자와 같은 시그니처가 있는 모든 메서드를 참조하는 변수를 선언할 수 있습니다.


이벤트 처리기 대리자의 표준 시그니처에서 값을 반환 하지 않는 메서드를 정의 합니다. 


첫 번째 매개 변수 형식이 Object 이벤트를 발생 시키는 인스턴스를 참조 합니다. 

두 번째 매개 변수 형식에서 파생 된 EventArgs 및 이벤트 데이터를 보유 합니다. 이벤트에서 이벤트 데이터를 생성 하지 않습니다 두 번째 매개 변수는 단순히 값의 경우는 EventArgs.Empty 필드입니다. 그렇지 않으면 두 번째 매개 변수에서 파생 된 형식입니다 EventArgs 하 고 모든 필드 또는 속성은 이벤트 데이터를 보관 하는 데 필요한을 제공 합니다.


EventHandler 대리자는 특별히 데이터를 생성 하지 하는 이벤트에 대한 이벤트 처리기 메서드를 나타내는 미리 정의된 대리자입니다. 


이벤트를 처리할 메서드와 이벤트를 연결하려면 대리자의 인스턴스를 해당 이벤트에 추가합니다. 대리자를 제거하지 않는 경우, 이벤트가 발생할 때마다 이벤트 처리기가 호출됩니다.


예제

    class Program
    {
        #region Event Publisher
        class Publisher
        {
            public event EventHandler Somethinghappened;

            public void DoSometing()
            {
                EventHandler hanlder = Somethinghappened;
                if (hanlder != null)
                    hanlder(this, EventArgs.Empty);
            }
        }
        #endregion

        #region event Subscriber
        class Subscriber
        {
            public void HanldeEvent(object sender, EventArgs e)
            {
                Console.WriteLine("Something happened to " + sender.ToString());
                Console.ReadLine();
            }
        }
        #endregion

        static void Main(string[] args)
        {
            Publisher publisher = new Publisher();
            Subscriber subscriber = new Subscriber();
            publisher.Somethinghappened += subscriber.HanldeEvent;

            publisher.DoSometing();
        }
    }

소스 파일 : 

MyEventHandler2.zip



2. EventHandler<TEventArgs> delegate


구문


[SerializableAttribute]

public delegate void EventHandler<TEventArgs>(

Object sender,

TEventArgs e

)



형식 매개 변수

TEventArgs

이벤트에서 생성한 이벤트 데이터의 형식입니다.


매개 변수

sender

형식: System.Object

이벤트 소스입니다.

e

형식: TEventArgs

이벤트 데이터를 포함하는 개체입니다. 



설명


.NET Framework의 이벤트 모델은 이벤트와 이벤트 처리기를 연결하는 이벤트 대리자가 있다는 사실을 기초로 만들어졌습니다. 이벤트를 발생시키려면 다음과 같은 두 가지 요소가 필요합니다.


  • 이벤트에 응답하는 메서드를 참조하는 대리자입니다.
  • 이벤트 데이터를 제공 하는 경우 이벤트 데이터를 보유하고 필요한 경우는 클래스입니다.


대리자는 시그니처를 정의하는 형식, 즉 메서드에 대한 반환 값 형식과 매개 변수 목록 형식입니다. 대리자 형식을 사용하여 대리자와 같은 시그니처가 있는 모든 메서드를 참조하는 변수를 선언할 수 있습니다.


이벤트 처리기 대리자의 표준 시그니처에서 값을 반환 하지 않는 메서드를 정의 합니다. 


첫 번째 매개 변수 형식이 Object 이벤트를 발생 시키는 인스턴스를 참조 합니다. 

두 번째 매개 변수 형식에서 파생 된 EventArgs 및 이벤트 데이터를 보유 합니다. 

이벤트에서 이벤트 데이터를 생성 하지 않습니다 두 번째 매개 변수는 단순히 값의 경우는 EventArgs.Empty 필드입니다. 그렇지 않으면 두 번째 매개 변수에서 파생 된 형식입니다 EventArgs 하 고 모든 필드 또는 속성은 이벤트 데이터를 보관 하는 데 필요한을 제공 합니다.


EventHandler<TEventArgs> 대리자는 미리 정의 된 데이터를 생성 하는 이벤트에 대한 이벤트 처리기 메서드를 나타내는 대리자입니다. 


이벤트에서 이벤트 데이터를 생성할 때 EventHandler<TEventArgs>을 사용하면 사용자 지정 대리자를 직접 코딩할 필요가 없습니다. 단순히 이벤트 데이터 개체의 형식을 제네릭 매개 변수로 제공합니다.


이벤트를 처리할 메서드와 이벤트를 연결하려면 대리자의 인스턴스를 해당 이벤트에 추가합니다. 대리자를 제거하지 않는 경우, 이벤트가 발생할 때마다 이벤트 처리기가 호출됩니다.




예제

    class Program
    {
        static void Main(string[] args)
        {
            Counter c = new Counter(new Random().Next(10));
            c.ThresholdReached += c_ThresholdReached;

            Console.WriteLine("press 'a' key to increase total");
            while (Console.ReadKey(true).KeyChar == 'a')
            {
                Console.WriteLine("adding one");
                c.Add(1);
            }            
        }

        static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
        {
            Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached);
            Console.ReadLine();
        }
    }

    class Counter
    {
        private int threshold;
        private int total;

        public Counter(int passedThreshold)
        {
            threshold = passedThreshold;
        }

        public void Add(int x)
        {
            total += x;
            if (total >= threshold)
            {
                ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
                args.Threshold = threshold;
                args.TimeReached = DateTime.Now;
                OnThresholdReached(args);
            }
        }

        protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
        {
            EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
    }

    public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }


소스 파일 :


MyEventHandler1.zip






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

람다식(Lambda Expression) - 2  (0) 2015.06.09
람다식(Lambda Expression) - 1  (0) 2015.06.08
Event 와 Delegate  (0) 2015.06.01
초단위 시간 경과 보이기  (0) 2015.05.12
로그인 창  (0) 2015.05.08
posted by 따시쿵
2015. 6. 1. 17:28 C#

프로그램 설명


이벤트와 델리게이트에 간단한 예제입니다.


1. 이벤트란?


1. A mechanism for communication between objects.

2. Used in building Loosely Coupled Applications.

   Encodo C# Handbook 7.30 – Loose vs. Tight Coupling

3. Helps Extending Applications.


오브젝트간에 통신(신호)을 담당하는 부분이며 Loosely Coupled 이 가장 큰 특징입니다.

 

 

델리게이트란?

 

1. Agreement / Contract between Publisher and Subscriber

2. Determines the signature of the event handler method in Subscriber

 

 

델리게이트와 이벤트를 만드는 순서


1. Define a delegate

2. Define an event based on that delegate 

3. Raise the event


2. 예제 시나리오를 위해서 3개의 클래스를 미리 만들어 두고, 여기에 델리게이트와 이벤트를 추가하는 것으로 하겠습니다.

 

전체적인 그림은 다음과 같으며, 기본 프로그램에 추가해 보도록 하겠습니다. 

 

기본 소스 파일 :

 

MainForm.cs MainForm.Designer.cs MainForm.resx Video.cs VideoEncoder.cs

 

mainform class

    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            Thread t_handler = new Thread(WorkingThread);
            t_handler.IsBackground = true;
            t_handler.Start();
        }

        private void WorkingThread()
        {
            var video = new Video() { Title = "video 1" };
            var videoEncoder = new VideoEncoder();

            videoEncoder.Encode(video, textBox1);
        }
    }

 

Video class

    public class Video
    {
        public string Title { get; set; }
    }

 

VideoEncoder class

    public class VideoEncoder
    {
        private delegate void SetDisplayText(string displayText, TextBox textbox1);
        public void Encode(Video video, TextBox textbox1)
        {
            TextDisplay("Encoding video...\n", textbox1);
            Thread.Sleep(3000);
            TextDisplay("End.", textbox1);
        }

        private void TextDisplay(string displayText, TextBox textbox1)
        {
            if(textbox1.InvokeRequired)
            {   
                textbox1.Invoke(new SetDisplayText(TextDisplay), displayText, textbox1);
                Application.DoEvents();
                return;
            }
            else
            {
                textbox1.AppendText(displayText + "\n");
            }
        }
    }

 

3. 델리게이트와 이벤트를 VideoEncoder class 에 정의합니다. (Publisher 정의)

    public class VideoEncoder
    {
        private delegate void SetDisplayText(string displayText, TextBox textbox1);

        // 1. Define a delegate
        // 2. Define an event based on that delegate
        // 3. Raise the event
        public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox textbpx1);
        public event VideoEncodedEventHandler VideoEncoded;

        public void Encode(Video video, TextBox textbox1)
        {
            TextDisplay("Encoding video...\n", textbox1);
            Thread.Sleep(3000);

            OnVideoEncoded(textbox1);

            TextDisplay("End.", textbox1);
        }

        private void TextDisplay(string displayText, TextBox textbox1)
        {
            if(textbox1.InvokeRequired)
            {   
                textbox1.Invoke(new SetDisplayText(TextDisplay), displayText, textbox1);
                Application.DoEvents();
                return;
            }
            else
            {
                textbox1.AppendText(displayText + "\n");
            }
        }
    }

 

이벤트를 호출합니다.

        protected virtual void OnVideoEncoded(TextBox textbox1)
        {
            if (VideoEncoded != null)
                VideoEncoded(this, EventArgs.Empty, textbox1);
        }

 

 

4. 이벤트 핸들러 구현합니다.(Subscriber 정의)

    public class MailService
    {
        public void OnVideoEncoded(object sender, EventArgs e, TextBox textbox1)
        {
            textbox1.Invoke((MethodInvoker)delegate
            {
                textbox1.AppendText("MailService: Sending an email....\n");
            });
        }
    }

    public class MessageService
    {
        public void OnVideoEncoded(object sender, EventArgs e, TextBox textbox1)
        {
            textbox1.Invoke((MethodInvoker)delegate
            {
                textbox1.AppendText("MessageService: Sending an message text....\n");
            });
        }
    }

 

5. 이벤트와 이벤트 핸들러를 추가합니다. (매개체 역할)  

            var video = new Video() { Title = "video 1" };
            var videoEncoder = new VideoEncoder();      // publisher
            var mailService = new MailService();        // subscriber
            var messageService = new MessageService();  // subscriber

            videoEncoder.VideoEncoded += mailService.OnVideoEncoded;
            videoEncoder.VideoEncoded += messageService.OnVideoEncoded;

            videoEncoder.Encode(video, textBox1);


현재까지 작업한 소스 파일 : MyEvnetnDelegate1.zip


6. 파라미터를 encapsulation 시켜서 구현하는 방법입니다.


파라미터를 숨길 VideoEventArgs class 를 추가 합니다.

    public class VideoEventArgs : EventArgs
    {
        public Video Video { get; set; }
    }

기존의 델리게이트 정의 부분의 두 번째 파라미터를 아래와 같이 VideoEventArgs class 로 변경합니다.


변경 전

public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox text1);

변경 후

public delegate void VideoEncodedEventHandler(object sender, VideoEventArgs args, TextBox text1);


이벤트를 호출하는 부분도 변경해 줍니다.


기존에 EventArgs 를 파라미터로 받는 부분을 VideoEventArgs 로 변경을 해 줍니다.


소스 파일 : 

MyEvnetnDelegate1(2).zip


7.EventHandler<TEventargs> 를 이용한 델리게이트


이벤트에서 이벤트 데이터를 생성할 때 EventHandler<TEventArgs>을 사용하면 사용자 지정 대리자를 직접 코딩할 필요가 없습니다. 단순히 이벤트 데이터 개체의 형식을 제네릭 매개 변수로 제공합니다.


VideoEventArgs class 를 다음과 같이 변경합니다.

    public class VideoEventArgs : EventArgs
    {
        public Video Video { get; set; }
        public TextBox Textbox1 { get; set; }
    }


다음 줄을 삭제합니다.

public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox text1);
public event VideoEncodedEventHandler VideoEncoded;


EventHanlder<TEventArgs> 델리게이트를 추가합니다.

public event EventHandler VideoEncoded;


소스 파일 : 

MyEvnetnDelegate1(3).zip



실행 화면





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

람다식(Lambda Expression) - 1  (0) 2015.06.08
EventHandler 와 EventHandler<TEventArgs> Delegate  (0) 2015.06.04
초단위 시간 경과 보이기  (0) 2015.05.12
로그인 창  (0) 2015.05.08
멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
posted by 따시쿵