HW2 GetFigureTypeFromName LINQ

public enum FigureType { Triangle, Square, Rectangle, Parallelogram, Rhombus, Trapezoid, Circle }

class Program
{
static Dictionary<string, FigureType> figureNameDic = new Dictionary<string, FigureType>();
static void SetFigureNameDictionary()
{
figureNameDic.Add(“삼각형”, FigureType.Triangle);
figureNameDic.Add(“Triangle”, FigureType.Triangle);
figureNameDic.Add(“TRIANGLE”, FigureType.Triangle);
figureNameDic.Add(“정사각형”, FigureType.Square);
figureNameDic.Add(“Square”, FigureType.Square);
figureNameDic.Add(“SQUARE”, FigureType.Square);
figureNameDic.Add(“직사각형”, FigureType.Rectangle);
figureNameDic.Add(“Rectangle”, FigureType.Rectangle);
figureNameDic.Add(“RECTANGLE”, FigureType.Rectangle);
figureNameDic.Add(“평행사변형”, FigureType.Parallelogram);
figureNameDic.Add(“Parallelogram”, FigureType.Parallelogram);
figureNameDic.Add(“PARALLELOGRAM”, FigureType.Parallelogram);
figureNameDic.Add(“마름모꼴”, FigureType.Rhombus);
figureNameDic.Add(“Rhombus”, FigureType.Rhombus);
figureNameDic.Add(“RHOMBUS”, FigureType.Rhombus);
figureNameDic.Add(“사다리꼴”, FigureType.Trapezoid);
figureNameDic.Add(“Trapezoid”, FigureType.Trapezoid);
figureNameDic.Add(“TRAPEZOID”, FigureType.Trapezoid);
figureNameDic.Add(“원”, FigureType.Circle);
figureNameDic.Add(“Circle”, FigureType.Circle);
figureNameDic.Add(“CIRCLE”, FigureType.Circle);
}

static FigureType? GetFigureTypeFromName(string str)
{
return figureNameDic.Where(x => x.Key.Contains(str)).Select(x => (FigureType?)x.Value).FirstOrDefault(); // FirstOrDefault returns the default value of a type if no item matches the predicate.
}

// 도형(Figure) 입력
static FigureType? GetInputFigure()
{
FigureType? inputFigure = null;
do
{
Console.Write(“도형의 종류를 입력해주세요(삼각형/정사각형/직사각형/평행사변형/마름모꼴/사다리꼴/원 등등 또는 Triangle/Square/Rectangle): “);
string str = Console.ReadLine();
inputFigure = GetFigureTypeFromName(str); // 입력된 도형에 따라서 enum 도형(Figure) 얻기
Console.WriteLine(“사용자 입력:{0} enum 도형:{1}”, str, inputFigure);
} while (inputFigure == null);
return inputFigure;
}

static void Main(string[] args)
{
SetFigureNameDictionary();
do
{
FigureType? inputFigure = GetInputFigure();
Console.WriteLine(“FigureType={0}”, inputFigure);
Console.WriteLine(“프로그램을 종료하려면 ESCAPE 키를 누르세요. 다시 계산하려면 ENTER 키를 누르세요.”);
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
}

Array.ConvertAll

https://msdn.microsoft.com/ko-kr/library/kt456a2y(v=vs.110).aspx

public delegate TOutput Converter<in TInput, out TOutput>(
TInput input
)

 static System.Drawing.Point Point2DrawingPoint(Point p)
{
     return (System.Drawing.Point)p;
}

static void Main(string[] args)
{

List<Point> Vertices = new List<Point>()
{
new Point() { X = 400, Y = 10 },
new Point() { X = 300, Y = 210 },
new Point() { X = 500, Y = 210 }
};

// 1. Lambda expression
System.Drawing.Point[] points1 = Array.ConvertAll(Vertices.ToArray(), x => (System.Drawing.Point)x); // Use with Point.cs type conversion operator overload

// 2. Anonymous method
System.Drawing.Point[] points2 = Array.ConvertAll(Vertices.ToArray(), delegate(Point x) { return (System.Drawing.Point)x; });

// 3. Delegate (Converter<TInput, TOutput>)
System.Drawing.Point[] points3 = Array.ConvertAll(Vertices.ToArray(), new Converter<Point, System.Drawing.Point>(Point2DrawingPoint));

foreach (var v in Vertices)
Console.WriteLine(v);
foreach (var p in points1)
Console.WriteLine(p);
foreach (var p in points2)
Console.WriteLine(p);
foreach (var p in points3)
Console.WriteLine(p);

}

LINQ

    class Category
    {
        public string Name { get; set; }
        public int ID { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // The Three Parts of a LINQ Query:
            //  1. Data source.
            int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

            // 2. Query creation.
            // numQuery is an IEnumerable<int>
            var numQuery =
                from num in numbers
                where (num % 2) == 0
                select num;

            // 3. Query execution.
            foreach (int num in numQuery)
            {
                Console.Write(“{0,1} “, num);
            }
            Console.WriteLine();

            // LIST
            List<Person> pList = new List<Person>();
            pList.Add(new Person(“둘리”, 1, “123-4568-9012”, “대한민국”));
            pList.Add(new Person(“희동이”, 3, “000-0000-0000”, “서울”));
            pList.Add(new Person(“고길동”, 2, “000-0000-0000”, “서울”));
            pList.Add(new Person(“도우너”, 5, “000-0000-0000”, “온따빠야별”));
            pList.Add(new Person(“또치”, 4, “000-0000-0000”, “미국”));
            pList.Insert(2, new Person(“마이콜”, 6, “000-0000-0000”, “서울”));

            // query syntax

            IEnumerable<Person> seoulQuery =
                from per in pList
                where per.Address == “서울”
                select per;

            foreach (var per in seoulQuery)
            {
                Console.WriteLine(per.Name + “, ” + per.ID);
            }
            Console.WriteLine();

            // query syntax
            IEnumerable<Person> personQuery =
                from p in pList
                where (p.ID < 2) || (p.Address == “서울”)
                orderby p.Name ascending
                select p;

            foreach (var p in personQuery)
            {
                Console.WriteLine(p.Name + “, ” + p.ID);
            }
            Console.WriteLine();

            // method syntax
            IEnumerable<Person> personQuery2 = pList.Where(p => (p.ID < 2) || (p.Address == “서울”)).OrderBy(p => p);
            foreach (var p in personQuery2)
            {
                Console.WriteLine(p.Name + “, ” + p.ID);
            }
            Console.WriteLine();

            // JOIN
            List<Category> categories = new List<Category>()
            {
                new Category() { Name=”서울”, ID=1 },
                new Category() { Name=”대한민국”, ID=2 },
                new Category() { Name=”미국”, ID=3 },
                new Category() { Name=”온따빠야별”, ID=4 },
            };

            var query = from p in pList
                        join cat in categories on p.Address equals cat.Name
                        select new
                        {
                            p.Name,
                            p.Address,
                            cat.ID
                        };
            Console.WriteLine(“Join Query”);
            foreach (var q in query)
            {
                Console.WriteLine(q.Name + “, ” + q.Address + “, ” + q.ID);
            }
            Console.WriteLine();
        }
    }

 

 

// 결과

0 2 4 6
희동이, 3
마이콜, 6
고길동, 2

고길동, 2
둘리, 1
마이콜, 6
희동이, 3

고길동, 2
둘리, 1
마이콜, 6
희동이, 3

Join Query
둘리, 대한민국, 2
희동이, 서울, 1
마이콜, 서울, 1
고길동, 서울, 1
도우너, 온따빠야별, 4
또치, 미국, 3

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# Collection Interface Delegate

CollectionInterfaceDelegateFileIOTest

http://msdn.microsoft.com/en-us/library/system.collections.generic(v=VS.80).aspx

Collections (예로, List, ArrayList, Hashtable등)은 ICollection<T> 인터페이스를 구현한다.
List 클래스의 경우는 IList<T> 인터페이스를 또한 구현한다.

List<T> 컬랙션 클래스의 메소드 (예를 들어, Exists, Find, TrueForAll 등)는 특정 헬퍼대리자 (예를 들어, delegate void Action<T>, delegate bool Predicate<T> 등과 같은)를 사용하여, 중복되는 코드를 간결하게 만들수있다.

HashCode

MSDN says:

A hash code is a numeric value that is used to identify an object during equality testing. It can also serve as an index for an object in a collection.

The GetHashCode method is suitable for use in hashing algorithms and data structures such as a hash table.

The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.

The GetHashCode method can be overridden by a derived type. Value types must override this method to provide a hash function that is appropriate for that type and to provide a useful distribution in a hash table. For uniqueness, the hash code must be based on the value of an instance field or property instead of a static field or property.

Objects used as a key in a Hashtable object must also override the GetHashCode method because those objects must generate their own hash code. If an object used as a key does not provide a useful implementation of GetHashCode, you can specify a hash code provider when the Hashtable object is constructed. Prior to the .NET Framework version 2.0, the hash code provider was based on the System.Collections.IHashCodeProvider interface. Starting with version 2.0, the hash code provider is based on the System.Collections.IEqualityComparer interface.

Basically, hash codes exist to make hashtables possible.
Two equal objects are guaranteed to have equal hashcodes.
Two unequal objects are not guaranteed to have unequal hashcodes (that’s called a collision).

CLASS INDEXER, PROPERTY, ABSTRACT, SEALED

Indexer (인덱서)
http://dis.dankook.ac.kr/lectures/hci09/entry/Indexer

Property (속성)
http://dis.dankook.ac.kr/lectures/hci09/entry/Property

Abstract Class (추상 클래스)
http://dis.dankook.ac.kr/lectures/hci09/entry/Abstract-class

Sealed Class (봉인 클래스)
http://dis.dankook.ac.kr/lectures/hci09/entry/Sealed-Class

polymorphism (다형성)
– Shape/Circle/Rectangle/Triangle/Square 클래스
– class 및 inheritance
– abstract class 및 polymorphism

ShapePolymorphism

Interface

Interface (인터페이스)
http://dis.dankook.ac.kr/lectures/hci09/entry/Interface 

IEnumerable & IEnumerator Interface
-IEnumerable 인터페이스는 foreach를 사용하여 컬랙션을 반복하는 것을 지원하기 위해 구현하여 사용한다.
http://dis.dankook.ac.kr/lectures/hci11/entry/IEnumerable
http://dis.dankook.ac.kr/lectures/hci09/entry/Enumerator

IEquatable Interface
-IEquatable 인터페이스는 두 객체간에 서로 내부 내용이 같은 지 (예: if(a == b))를 비교하기 위해 구현하여 사용한다.
http://dis.dankook.ac.kr/lectures/hci11/entry/IEquatable
http://dis.dankook.ac.kr/lectures/hci10/72
http://dis.dankook.ac.kr/lectures/hci09/entry/Equals

IComparable Interface
-IComparable 인터페이스는 개체에 대한 기본 정렬(sort) 순서를 지정해주기 위해 구현하여 사용한다. 해당 개체를 배열이나 컬랙션에서 정렬하는데 필요하다.
http://dis.dankook.ac.kr/lectures/hci11/entry/IComparable

GENERIC LIST CLASS

<<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, 크면 양수를 반환하는 메소드