C# Collection, Interface, Delegate

1. Collection
서로 밀접하게 관련된 데이터를 그룹화하여 좀 더 효율적으로 처리할 수 있게 한 특수한 클래스 혹은 구조체이다.


2. Collection과 Interface
모든 닷넷 컬렉션은 ICollection<T> 인터페이스는 구현한다.
IList<T> 인터페이스는 인덱스를 사용하여 요소에 개별적으로 접근할 수 있는 컬렉션을 정의한다.
-T this [int index] { get; set; } //지정한 인덱스에 있는 요소를 가져오거나 설정
-int IndexOf(T item)              //IList에서 특정 항목의 인덱스를 확인
-void Insert(int index, T item)   //항목을 IList의 지정한 인덱스에 삽입
-void RemoveAt(int index)         //지정한 인덱스에서 IList 항목을 제거


3. Collection과 Method와 Delegate
// Person 클래스
public class Person
{
     private readonly string _name;


     public string Name
     {
         get { return _name; }
     }


     private readonly int _age;


     public int Age
     {
         get { return _age; }
     }


     public Person(string name, int age)
     {
         _name = name;
         _age = age;
     }


     public override string ToString()
     {
         return string.Format(“이름 : {0}\t나이 : {1}”, _name, _age);
     }
}


// List<T> 컬렉션에 Person 객체를 담는다
private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));
}


// aList에 포함된 세 사람이 모두 10세 이상인지를 확인한다 => 둘리와 고길동만 만족함
private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


     bool result = true;
     foreach (Person p in aList)
     {
         if (p.Age < 10)
         {
             result = false;
             break;
         }
     }
}


// aList에 포함된 세 사람이 모두 이름이 두 글자인지를 확인한다 => 둘리만 만족함
private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


     bool result = true;
     foreach (Person p in aList)
     {
         if (p.Name.Length != 2)
         {
             result = false;
             break;
         }
     }
}


// 위의 두 코드가 나이가 10세이상인지 또는 이름이 두 글자인지 조건을 만족하는지를 확인하는 부분이 반복
// List<T> 컬렉션의 TrueForAll 메소드는 조건을 만족하는 메소드가 존재한다면 true반환
public delegate bool Predicate<T>(T item);


public class List<T> : …
{
     …


    public bool TrueForAll(Predicate<T> match)
    {
        bool result = true;
        foreach (T item in this)
        {
            if (match(item) == false)
            {
                result = false;
                break;
            }
        }
    }
}


private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


    // 10살 이상인지를 검사
    bool result1 = aList.TrueForAll(IsGreaterThanTen);


    // 무명 대리자를 사용하여 이름이 두 글자인지 검사
    bool result2 = aList.TrueForAll(delegate(Person p)
                                    { return p.Name.Length == 2; });
}


private static bool IsGreaterThanTen(Person p)
{
    return p.Age >= 10;
}

4. List<T> 컬랙션 클래스의 메소드와 헬퍼 대리자


public List<TOutput> ConvertAll<TOutput> (Converter<T, TOutput> converter)
-리스트 객체의 각 원소를 TOutput 형으로 변환하여 리스트로 반환


public bool Exists(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 원소가 있는지 여부를 반환


public T Find(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 첫번째 원소를 반환


public List<T> FindAll(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 모든 원소를 리스트로 반환


public int FindIndex(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 첫번째 원소의 인덱스를 반환


public int FindLastIndex(Predicate<T> match)
-리스트에 있는 모든 원소 중 match 조건을 만족하는 마지막 원소의 인덱스를 반환


public void ForEach(Action<T> action)
-리스트에 있는 모든 원소에 대해 action을 수행


public bool TrueForAll(Predicate<T> match)
-리스트에 있는 모든 원소가 match 조건을 만족하는 지 여부를 반환


<<대리자(Delegate)>>


public delegate void Action<T>(T object)
-T 형의 매개변수를 하나 받고 반환값이 없는 메소드


public delegate TOutput Converter<TInput, TOutput>(TInput input)
-TInput 형의 매개변수를 받고 이를 TOutput 형으로 변환하여 반환하는 메소드


public delegate bool Predicate<T>(T object)
-T 형의 매개변수를 받아 그것이 특정 조건을 만족하는지를 반환하는 메소드


public delegate int Comparison<T>(T x, T y)
-x, y 두 객체를 비교하는 메소드로 x가 y보다 작으면 음수, 같으면 0, 크면 양수를 반환하는 메소드


5. List<T>의 Sort 메소드
public void Sort()
public void Sort(Comparison<T> comparison)
public void Sort(IComparer<T> comparer)
public void Sort(int index, int count, IComparer<T> comparer)


-public void Sort()
즉, 매개변수가 없는 Sort 메서드(void Sort())는 List<T>의 원소인 객체와 계약을 맺었는데,
그 계약의 내용은 List<T>의 원소인 객체는 int CompareTo(T other)와 같은 메서드를 가지고 있다는 것입니다.
따라서 실제 List<T>의 원소의 객체가 무엇이든지 간에 Sort 메서드는 그 객체의 CompareTo 메서드를 호출하면 정렬을 수행할 수 있다.
List<T>의 원소인 객체는 int CompareTo(T other)를 구현하여야 한다.
즉, Person이 int CompareTo(Person other) 메소드에 이름 순으로 구현하여야 계약이 성립한다.


public class Person : IComparable<Person>
{
    ….

     // Sort
     public int CompareTo(Person other)
    {
        return this.Name.CompareTo(other.Name);
    }
}


private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


    // 이름순으로 정렬
    aList.Sort();
}

-public void Sort(Comparison<T> comparison)
이번에는 이름이 아니라 나이 순으로 정렬을 하는 경우,
int CompareTo(Person other) 내부 구현을 이름이 아니라 나이를 기준으로 정렬하도록 수정한다.
이 경우 동적으로 Sort를 다르게 할수없는 문제가 있으므로,
List<T>의 원소를 비교 가능한 객체라고 전제 하는 것이 아니라,
Sort 메서드의 매개 변수로 아예 List<T>의 원소들을 비교하는 메서드를 전달하는 것입니다.

public delegate int Comparison<T>(T x, T y)
Comparison 대리자의 의미는 x가 y보다 작으면 음수, 같으면 0, 크면 양수를 반환한다는 것이다.

public static int ComparePersonByName(Person x, Person y)
{
    return x.Name.CompareTo(y.Name);
}

public static int ComparePersonByAge(Person x, Person y)
{
    return x.Age.CompareTo(y.Age);
}


private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


    // 이름순으로 정렬
    aList.Sort(ComparePersonByName);
    // 나이순으로 정렬
    aList.Sort(ComparePersonByAge);
}

-public void Sort(IComparer<T> comparer)
Sort가 IComparer<T> 인터페이스를 매개변수로 받아 처리할 수 있다.
int Compare(T x, T y)

public class PersonNameComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Name.CompareTo(y.Name);
    }
}


public class PersonAgeComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Age.CompareTo(y.Age);
    }
}


private static void Main(string[] args)
{
    List<Person> aList = new List<Person>();
    aList.Add(new Person(“둘리”, 1000));
    aList.Add(new Person(“희동이”, 3));
    aList.Add(new Person(“고길동”, 40));


    // 이름순으로 정렬
    aList.Sort(new PersonNameComparer());
    // 나이순으로 정렬
    aList.Sort(new PersonAgeComparer());


    foreach(Person p in aList)
        Console.WriteLine(p); // Person의 ToString 호출
}

C# Serialization

Person Serialization (Using BinaryFormatter or SoapFormatter)
http://dis.dankook.ac.kr/lectures/hci09/entry/Simple-Serialization

Person XML Serialization (Using XML Serializer or Soap XML Serializer)
http://dis.dankook.ac.kr/lectures/hci09/entry/XML-Serialization

Person Using ISerialable Interface
http://dis.dankook.ac.kr/lectures/hci09/entry/ISerialable

PersonList Serialization (Using BinaryFormatter or SoapFormatter)
http://dis.dankook.ac.kr/lectures/hci09/entry/PersonList-Serialization

Convert (Longitude, Latitude) to (X, Y) on a map

 // Get the latitude as a value between 0 and 180,
// where the negative values represent values South of the Equator
            double latitude = lat + 90.0;
// Get the longitude as a value between 0 and 360,
// where the negative values represent values West of the Greenwich Meridian.
            double longitude = lon + 180.0;


// calculate how many pixels are needed to represent each degree for width and height
            double pixelsWidth = map.Width/360.0;
            double pixelsHeight = map.Height/180.0;


// Calculate how many pixels we need to represent our latitude value
            double latitudePixels = latitude * pixelsHeight;
// Calculate how many pixels we need to represent our longitude value
            double longitudePixels = longitude * pixelsWidth;


// The X coordinate of our point is the longitudePixels value
            float x = (float)longitudePixels;
// The Y coordinate of our point is 180-latitude
// since the Y axis is facing down but the map is facing up
            float y = (float) ((180.0 * pixelsHeight) – latitudePixels);

Draw Shapes to Bitmap in Memory

도형그리기를 비트맵이미지로 그리기1273706404.zip
private void Form1_Paint(object sender, PaintEventArgs e)
{
            Graphics g = e.Graphics;


            // Create a Bitmap image in memory and set its CompositingMode
            Bitmap bmp = new Bitmap(this.Size.Width, this.Size.Height,
                                                              PixelFormat.Format32bppArgb);
            Graphics gBmp = Graphics.FromImage(bmp);
            gBmp.CompositingMode = CompositingMode.SourceCopy;


            // Pen으로 대각선과 사각형 그리기 (to bitmap in memory)
            Pen p = new Pen(Color.Black, 3);
            Rectangle r = new Rectangle(10, 10, this.Size.Width/2, this.Size.Height/2);
            gBmp.DrawLine(p, 10, 10, this.Size.Width / 2 + 10, this.Size.Height / 2 + 10);
            gBmp.DrawLine(p, this.Size.Width / 2 + 10, 10, 10, this.Size.Height / 2 + 10);
            gBmp.DrawRectangle(p, r);


            // Brush로 파란사각형 그리기 (to bitmap in memory)
            Brush b = new SolidBrush(Color.Blue);
            Rectangle r2 = new Rectangle(this.Size.Width / 2 + 10, this.Size.Height / 2 + 10,
                                                                    this.Size.Width / 2 – 10, this.Size.Height / 2 – 10);
            gBmp.FillRectangle(b, r2);


            // Brush로 빨간삼각형 그리기 (to bitmap in memory)
            Brush b2 = new SolidBrush(Color.Red);
            Point[] pt = new Point[3];
            pt[0].X = 400; pt[0].Y = 10;
            pt[1].X = 300; pt[1].Y = 210;
            pt[2].X = 500; pt[2].Y = 210;
            gBmp.FillPolygon(b2, pt);


            // HatchBrush로 타원 그리기 (to bitmap in memory)
            HatchBrush hb = new HatchBrush(HatchStyle.DiagonalCross,
                                                                           Color.Yellow, Color.Brown);
            gBmp.FillEllipse(hb, 10, 220, 200, 100);


            // DrawArc 메소드 사용하여 호 그리기 (to bitmap in memory)
            Pen p2 = new Pen(Color.Green, 3);
            Rectangle r3 = new Rectangle(220, 220, 200, 100);
            gBmp.DrawArc(p2, r3, 0, 180);


            // draw the bitmap on our window
            g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
            bmp.Dispose();
            gBmp.Dispose();
    }

ListView Item Edit

private void editToolStripMenuItem1_Click(object sender, EventArgs e)
{
            if (listView1.FocusedItem == null) return;
            int index = listView1.FocusedItem.Index;
            PersonForm personForm1 = new PersonForm();
            personForm1.Owner = this;
            personForm1.textBox1.Text = listView1.Items[index].SubItems[0].Text;
            personForm1.textBox2.Text = listView1.Items[index].SubItems[1].Text;
            personForm1.textBox3.Text = listView1.Items[index].SubItems[2].Text;
            personForm1.textBox4.Text = listView1.Items[index].SubItems[3].Text;
            if (personForm1.ShowDialog() == DialogResult.OK)
            {
                Person p = new Person();
                p.Name = personForm1.textBox1.Text;
                p.ID = int.Parse(personForm1.textBox2.Text);
                p.Phone = personForm1.textBox3.Text;
                p.Address = personForm1.textBox4.Text;
                pList[index] = p;
                listView1.Items[index] = p.ToListViewItem();
            }
}

To Prevent Multiple Show of the same Modeless Form

        private void findToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 현재 열려있는 비모달형 폼 중복생성 방지
            bool formExist = false;


            foreach (Form f in Application.OpenForms)
            {
                if (f.GetType() == typeof(
FindPersonForm))
                {
                    f.Activate();
                    formExist = true;
                }
            }


            if (!formExist)
            {
                FindPersonForm f = new FindPersonForm();
                f.Owner = this;
                f.Show();
                f.Activate();
            }
        }

Number Only Textbox

// number only textbox using TryParse
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    int value = 0;
    e.Handled = !int.TryParse(e.KeyChar.ToString(), out value);
}

// number only textbox using Regex.IsMatch
private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), “\\d+”))
        e.Handled = true;
}

// NumberTextBoxLib custom control (inherited from TextBox)
public partial class NumberTextBox : TextBox
{
        public NumberTextBox()
        {
            InitializeComponent();
        }


        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);
            int value = 0;
            e.Handled = !int.TryParse(e.KeyChar.ToString(), out value);
        }
}2213568150.zip

GDI+

GDI+ A Higher Level API
http://www.csharphelp.com/archives3/files/archive593/GDI.pdf

Pen
http://dis.dankook.ac.kr/lectures/hci09/entry/Pen

Brush
http://dis.dankook.ac.kr/lectures/hci09/entry/Brush

Image
http://dis.dankook.ac.kr/lectures/hci09/entry/DrawImage

ImageAttribute
http://dis.dankook.ac.kr/lectures/hci09/entry/ImageAttributes

ImageTransform
http://dis.dankook.ac.kr/lectures/hci09/entry/DrawImageTransform

DoubleBuffering
http://dis.dankook.ac.kr/lectures/hci09/entry/DoubleBuffering

Graphic Path
http://dis.dankook.ac.kr/lectures/hci09/entry/PathScribble

Draw Freedraw line & rubber band line
http://dis.dankook.ac.kr/lectures/hci10/entry/Rubber-band-line-drawing

Draw shapes
http://dis.dankook.ac.kr/lectures/hci10/entry/Draw-Shape

DrawImageObjects
http://dis.dankook.ac.kr/lectures/hci10/entry/DrawImageObjects