Bloggang.com : weblog for you and your gang

Just algorithm!

แก้โจทย์ Knight's Tour ด้วย C#

ช่วงนี้ไม่ค่อยมีเวลามาเขียนโปรแกรมแก้โจทย์ Algorithm เล่นนานละ
แต่ไปเจอโจทย์นึงที่ Web TwoGuru ชื่อว่า Knight's Tour
น่าสนใจเลยลองเขียนดูบ้าง



Knight's Tour คือ การเดินม้าในตารางหมากรุก 8x8
โดยเริ่มที่ช่องใดก็ได้ เดินไปเรื่อย ๆ ห้ามทับจุดเดิม และเดินให้ครบทุกช่อง
เห็นโจทย์ก็รู้เลยน่าสนใจ
ซึ่งดูผิวเผินน่าจะยาก จากการคำนวนของ Web TwoGuru เห็นว่ามีรูปแบบเป็น สี่แสนล้านล้านล้านล้านล้านล้านรูปแบบ !!! Smiley
แต่คิดว่าหลักการของ Functional Programming น่าจะแก้ปัญหานี้ได้ไม่ยาก Smiley

ไม่พูดพร่ำทำเพลง เขียนรูปแบบการเดินของม้าก่อนเลย

int[][] moves = new[] {
                    new[] {+1, -2},
                    new[] {+2, -1},
                    new[] {+2, +1},
                    new[] {+1, +2},
                    new[] {-1, +2},
                    new[] {-2, +1},
                    new[] {-2, -1},
                    new[] {-1, -2},
};


ต่อด้วยหากระดาน กระดาน 8x8 ซึ่งใช้ 64 ช่อง
ตอนแรกคิดว่าจะใช้ BitArray ขนาด 64 ช่อง แต่คิดไปคิดมา
ulong ก็เป็น Type ที่มี 64bit นี่หว่า เลยตัดสินใจใช้ ulong
ก็เลยต้องเขียนสูตรการแปลงจากตำแหน่งบนกระดานเป็น ulong และก็แปลงกลับ

Func<int[], ulong> positionToULong = pos => 1UL << (pos[1] * 8 + pos[0]);
Func<ulong, int[]> ulongToPosition = u => {
    int log2 = 0, x, y;
    while (u != 1) {
        log2++;
        u >>= 1;
    }
    y = Math.DivRem(log2, 8, out x);
    return new[] { x, y };
};


ต่อมาก็เขียนสูตรการเดินของม้าซะ
ในแต่ละช่องม้าสามารถเดินไปจุดไหนบ้างใช้สูตรนี้

Func<ulong, ulong[]> nextPoint = u => {
    var pos = ulongToPosition(u);
    return (from move in moves
            select new[] { pos[0] + move[0], pos[1] + move[1] } into nextPos
            where nextPos[0] >= 0 && nextPos[0] < 8 &&
                  nextPos[1] >= 0 && nextPos[1] < 8
            select positionToULong(nextPos)).ToArray();
};
nextPoint = nextPoint.Memoize();


ในสูตรถ้าม้าตัวไหนเดินออกนอกตารางก็ตัดทิ้งไป
แล้วก็จะเห็นคำสั่ง Memoize ในบรรทัดสุดท้าย
เป็นการทำให้ Function จำคำตอบได้ไม่ต้องคำนวณใหม่
อ่าน Article เก่า เพิ่มเติมครับ

และก็มาถึง Function สุดท้าย
เป็น Algorithm การเดินม้าให้ครบ 64 ตาแล้วครับ

Func<ulong, ulong, IEnumerable<IEnumerable<ulong>>> func = null;
func = (board, u) => {
    //ถ้าเดินทับจุดเดิม ก็ไม่มีผลลัพธ์
    if ((board & u) > 0)
        return Enumerable.Empty<IEnumerable<ulong>>();

    //ถ้าเดินครบ 64 ตา ก็คืนค่าตำแหน่งสุดท้าย
    var newBoard = board | u;
    if (newBoard == ulong.MaxValue)
        return u.ToEnumerable().ToEnumerable();

    //เอาตาเดินม้าถัดไป มาวนใส่ Function นี้
    //ได้ผลลัพธ์ ก็เอาตำแหน่งปัจจุบันมารวมกับคำตอบที่ได้
    return from px in nextPoint(u)
           from sol in func(newBoard, px)
           select new[] { u }.Concat(sol);
};


ป๊าด!!! จบแล้วครับ เริ่มรันได้เลย Smiley

var result = (from pos in func(0, 1).First().Select(ulongToPosition).WithIndex()
              group pos by pos.B[1] into g
              orderby g.Key
              select (from pos2 in g
                      orderby pos2.B[0]
                      select pos2.A.ToString("00")).Join(" ")).Join("rn");
Console.WriteLine(result);

//00 37 54 33 02 35 18 21
//53 46 01 36 19 22 03 16
//38 55 32 45 34 17 20 09
//47 52 39 56 23 10 15 04
//58 31 44 51 40 25 08 11
//43 48 57 24 61 14 05 26
//30 59 50 41 28 07 12 63
//49 42 29 60 13 62 27 06


ใช้เวลาไป 2 วินาทีกว่า ๆ!! Smiley
โค๊ดแปลงเป็นตารางมี Function แปลก ๆ ไม่ต้องงงว่ามาจากไหน
เป็น Function ที่ผมเขียนใช้เอง
สนใจไปหาดาวน์โหลดใน Framework ของผมนะครับ Smiley

เพื่อนผมมันบอกว่า Functional Programming อ่านยาก
เอาไปใช้ใน Production ไม่ได้
ผมก็ว่าจริงครับ ถ้าเขียนแล้วคนอื่นอ่านไม่เข้าใจ ก็เป็นโค๊ดที่ Maintain ไม่ได้
แต่มันก็เขียนสนุกครับ ตอนนี้เลยได้แต่เขียนคนเดียว มันส์คนเดียว Smiley
คนไหนเขียน Functional Programming บ้าง ยกมือขึ้นครับ !!! (จะมีมั้ยเนี่ย หายากจริง ๆ)

 

Create Date : 04 สิงหาคม 2552
Last Update : 4 สิงหาคม 2552 0:45:26 น.  

[C#] แก้ปัญหา 180 IQ ด้วย LINQ

สวัสดีครับ ไม่ได้เขียนใน Blog นี้นานมาก งานมันเยอะ (ข้ออ้าง Smiley)
ก่อนอื่นขอประชาสัมพันธ์
ผมมีแผนจะทำ Training ให้บริษัท
โดยจะเอาเนื้อหามาทำเป็น Blog ด้วย
เนื้อหาจะเกี่ยวกับวิธีการทำให้เขียน Program ได้ดีขึ้น
แต่ไม่ได้เขียนที่ Blog นี้นะครับ
จะไปเขียนที่ CoreSharp.net web community ของเพื่อนผมเองครับ Smiley
(ที่ไม่เขียนใน Blog นี้ เพราะ Target Audience เป็นผู้เขียน Program ทั่ว ๆ ไป
แต่ Blog นี้ เขียนตามความสะใจของเจ้าของ Blog Smiley)
ยังไงก็ติดตามนะครับ อัพเรื่อย ๆ

เพื่อน ๆ รู้จักเกม 180 IQ ไหมครับ (ถ้ารู้จักแปลว่าแก่แล้ว Smiley)
เป็นเกมที่จะให้เลขมาจำนวนนึง เช่น ให้เลข 1 2 5 8 มา
คุณจะ บวก ลบ คูณ หาร เลขสี่ตัวนี้ยังไง ให้ได้ผลลัพธ์ที่ต้องการ เช่น 27
คุณอาจจะเอา 8+5 ได้ 13 แล้วคูณด้วย 2 ได้ 26
แล้วบวก 1 ได้ 27
ง่ายไหมครับ? Smiley
ลองแก้ปัญหาดูสักข้อก่อนอ่านต่อไป
1 2 5 8 = 44

...

ทีนี้ลองคิดดูว่าคุณจะ Solve ปัญหานี้โดยใช้ Computer ยังไง
จากตัวอย่างด้านบน ((8+5)*2) + 1 = 27
คุณจะเห็นว่าเลข 1 2 5 8 มันสลับกันไปหมดการสลับนี้ เราเรียกว่า Permutation ครับ
คุณสามารถสลับ 1 2 5 8 ได้ 4! = 24 วิธี

ต่อมาดูที่เครื่องหมาย + - * / คุณอาจจะใช้ + - * / มากกว่า 1 ครั้งก็ได้
การสลับแบบที่ใช้ตัวเลือกได้มากกว่า 1 ครั้ง เราเรียกว่า Permutation with Repetition ครับ
คุณสามารถสลับ + - * / ได้ อย่างละ 3 ครั้ง เป็น 4^3 = 64 วิธี

ต่อมาดูที่วงเล็บ คุณสามารถสลับวงเล็บได้ 5 วิธี คือ
(((a b) c) d)
((a (b c)) d)
((a b) (c d))
(a ((b c) d))
(a (b (c d)))
วิธีการสลับวงเล็บแบบนี้เราเรียกว่า Binary Bracketing

สรุปว่า วิธีการทั้งหมดที่จะทำให้เกิดคำตอบมีทั้งหมด 24 * 64 * 5 = 7,680 วิธี
เนื่องจาก Search Space มันแค่หลักพัน เราก็ให้ Computer มันหาทุกวิธีเลย
แล้วเอาคำตอบออกมา

แล้วการทำ Permutation กะ Binary Bracketing เนี่ยทำยังไงล่ะครับ
อย่าไปเครียด ผมทำไว้ให้คุณแล้ว อิอิ
เชิญไป Download ที่ CodePlex ครับ Smiley
Library ชื่อ Combinatorics นะครับ
ผมทำไว้เป็น OpenSource ถ้าสนใจ Code ก็ลองเอาไปดูได้ว่า
Library สำหรับ Permutation กะ Binary Bracketing เนี่ย ทำยังไง

ก่อนอื่น ประกาศกลุ่มของตัวเลขก่อนครับ 1 2 5 8

var nums = new Expression[] {
                   Expression.Constant(1.0),
                   Expression.Constant(2.0),
                   Expression.Constant(5.0),
                   Expression.Constant(8.0) };


ต่อมาประกาศกลุ่มของ Operation คือ + - * /

var operations = new Func<Expression, Expression, Expression>[] {
                   Expression.Add,
                   Expression.Subtract,
                   Expression.Multiply,
                   Expression.Divide };


จะเห็นว่าผมประกาศเป็น Expression ทั้งหมด
เพราะผมต้องการแสดง Expression ของผลลัพธ์ด้วย
ถ้าคุณต้องการแค่ผลลัพธ์ ก็ใช้ double แทน Expression ไปเลย
ทำงานเร็วกว่ากันเยอะ
อ่านให้เข้าใจ รับรองประยุกต์ใช้ไม่ยาก

                //Permute ตัวเลขทั้งหมด
var solutions = from numsPermute in nums.Permute()

                //Permutation with Repetition operation
ทั้งหมด 3 ที
                from opsPermute in operations.Permute(3, CombinatoricModel.Repetition)

                //เอาตัวเลข และ operation ต่าง ๆ ไป
ทำ Binary Bracketing
                from results in numsPermute.BinaryBracketing(opsPermute)

                //
แปลง Expression เป็นผลลัพธ์
                let computed = Expression.Lambda<Func<double>>(results).Compile()()

                //
เลือกเฉพาะค่า 1 - 100
                where computed > 0.0 &&
                      computed <= 100.0 &&
                      Math.Floor(computed) == computed

                //
จัดกลุ่มตามผลลัพธ์
                group results by computed into g

                //
จัดเรียงตามผลลัพธ์
                orderby g.Key

                //
คืนค่า ผลลัพธ์ และ Expression ตัวแรก
                select string.Format("{0} = {1}", g.Key, g.First());

//
แสดงผล
solutions.ForEach(s => Console.WriteLine(s));
//1 = ((1 + (2 + 5)) / 8)
//2 = ((1 - (2 + 5)) + 8)
//3 = (1 + ((2 * 5) - 8))
//4 = (((1 + 5) * 2) - 8)
//5 = (((1 * 2) - 5) + 8)
//6 = (1 + ((2 - 5) + 8))
//7 = (((1 + 2) * 5) - 8)
//8 = (((1 - 5) + 8) * 2)
//9 = (((1 / 2) * 8) + 5)
//10 = (1 + (5 + (8 / 2)))
//11 = ((1 * (2 * 8)) - 5)
//12 = (((1 - 2) + 5) + 8)
//13 = (((1 + 8) * 2) - 5)
//14 = (((2 - 1) + 5) + 8)
//15 = (((1 * 2) + 5) + 8)
//16 = (1 + (2 + (5 + 8)))
//17 = (((2 * 5) - 1) + 8)
//18 = ((1 * (2 * 5)) + 8)
//19 = (1 + ((2 * 5) + 8))
//20 = (((1 / 2) * 5) * 8)
//21 = ((1 * (2 * 8)) + 5)
//22 = (1 + ((2 * 8) + 5))
//23 = (((1 + 2) * 5) + 8)
//24 = ((1 - 5) * (2 - 8))
//25 = (1 - ((2 - 5) * 8))
//26 = (1 * (2 * (5 + 8)))
//27 = (1 + (2 * (5 + 8)))
//28 = ((1 + (5 / 2)) * 8)
//29 = (((1 + 2) * 8) + 5)
//30 = (1 * (5 * (8 - 2)))
//31 = (1 - ((2 - 8) * 5))
//32 = (((1 - 2) + 5) * 8)
//33 = ((5 * (8 - 1)) - 2)
//34 = (2 - ((1 - 5) * 8))
//35 = (((1 - 2) + 8) * 5)
//36 = ((1 + 5) * (8 - 2))
//37 = (2 - ((1 - 8) * 5))
//38 = ((1 * (5 * 8)) - 2)
//39 = ((1 - 2) + (5 * 8))
//40 = ((2 - 1) * (5 * 8))
//41 = ((2 - 1) + (5 * 8))
//42 = ((1 * 2) + (5 * 8))
//43 = (1 + (2 + (5 * 8)))
//44 = (((1 / 2) + 5) * 8)
//45 = (((2 - 1) + 8) * 5)
//46 = (((1 + 5) * 8) - 2)
//47 = (((1 + 8) * 5) + 2)
//48 = (((2 - 1) + 5) * 8)
//49 = ((2 + 5) * (8 - 1))
//50 = (((1 * 2) + 8) * 5)
//51 = (1 + ((2 + 8) * 5))
//55 = ((1 + (2 + 8)) * 5)
//56 = (((1 * 2) + 5) * 8)
//57 = (1 + ((2 + 5) * 8))
//60 = ((1 + 5) * (2 + 8))
//63 = ((1 + 8) * (2 + 5))
//64 = ((1 + (2 + 5)) * 8)
//70 = (2 * (5 * (8 - 1)))
//72 = (((2 * 5) - 1) * 8)
//75 = (((2 * 8) - 1) * 5)
//78 = (2 * ((5 * 8) - 1))
//79 = ((2 * (5 * 8)) - 1)
//80 = (1 * (2 * (5 * 8)))
//81 = (1 + (2 * (5 * 8)))
//82 = ((1 + (5 * 8)) * 2)
//85 = ((1 + (2 * 8)) * 5)
//88 = ((1 + (2 * 5)) * 8)
//90 = ((1 + 8) * (2 * 5))
//96 = ((1 + 5) * (2 * 8))


แว๊ก! คำตอบออกมาเพียบเลย
จะเห็นว่าเขียนดี ๆ คุณสามารถแก้ปัญหา 180 IQ ได้ ด้วย Code LINQ ไม่เกิน 8 บรรทัด!!!
จบแล้วครับ ทีนี้จะหาเลขอะไรก็ง่าย ๆ แล้วใช่ไหมครับ Smiley

 

Create Date : 26 เมษายน 2552
Last Update : 26 เมษายน 2552 21:58:10 น.  

มีอะไรใหม่ใน C# 4.0

เมื่อสักครู่ เพิ่งดู Video Future of C# ของ Anders Hejlsberg จบ
ประทับใจมาก เลยเอามาเขียนสรุปคร่าว ๆ มาให้อ่านกัน

ประวัติของ C#
C# 1.0 - คือ จุดเริ่มต้นของภาษา C แบบ Managed Code ซึ่งทำให้การเขียน Code ปลอดภัยและไม่ซับซ้อน ไม่ต้องยุ่งกับ Memory
C# 2.0 - เพิ่ม Generics (และ features อีกมากมาย) ทำให้ Collections ต่าง ๆ Type Safety และมีประสิทธิภาพ
C# 3.0 - Version ปัจจุบัน
 เพิ่ม LINQ ทำให้เราสามารถ Query Collections ต่าง ๆ ง่ายดาย
และ C# 4.0 - คือยุคของ Dynamic Programming ซึ่งจะพูดถึงต่อไป

แนวโน้มของภาษา
Declarative - คือ แค่บอกว่าจะทำอะไร ไม่ต้องระบุว่าจะทำอย่างไร เช่น LINQ แค่สั่ง orderby ไม่ต้องเขียน for-loop
Dynamic - เพื่อให้ทำงานร่วมกับภาษา Dynamic ต่าง ๆ เช่น Python, Ruby, JavaScript, และ COM
Concurrency - ปกติการเขียน Code แบบ Muti-Thread จะยุ่งยาก แต่ Parallel Library จะจัดการส่วนที่ยุ่งยากให้

สิ่งใหม่ ๆ ใน C# 4.0
Dynamic Language Support
Feature ชูโรงของ C# 4.0
Static Type คือ การกำหนด Type และกำหนด Method ต่าง ๆ ตอน Compile ทำให้ Application มีประสิทธิภาพ
แต่ Dynamic Type จะกำหนด Type และ Method ที่ใช้ตอน Runtime ซึ่งมีข้อดีคือเขียนง่าย เร็ว
C# 4.0 บอกว่าต่อไปนี้เราจะมี Type พิเศษ คือ dynamic
ถ้า object ไหนเป็น dynamic ก็จะเรียก Method, Property, หรือ Index อะไรก็ได้ เช่น

dynamic d = GetDynamic();
d.Foo();
Object "d" อาจไม่มี method ชื่อ Foo ก็ได้ แต่จะ Compile ผ่านเสมอ
มีประโยชน์ เช่น App ของ SilverLight เวลาไปคุยกับ JavaScript
ทำให้ SilverLight สามารถเรียกคำสั่งต่าง ๆ ใน JavaScript ได้เลย
(ใน Demo จะมีการเลือกชื่อ Contact ใน SilverLight
แล้วตอนเลือก .Net จะเรียกคำสั่งดึงข้อมูล Map ผ่าน JavaScript
แล้วเอาข้อมูลของ Map นั้นมาแสดงใน SilverLight)

Optional and Named Parameters
เป็น Feature ล้าหลังมาก ซึ่ง VB.NET มีตั้งแต่ Version แรกแล้ว
ปกติเราจะเขียน Method นึงที่รับหลาย ๆ parameter
แต่บาง parameter มี default value ซึ่งไม่ต้องใส่ก็ได้
ก่อนหน้านี้เราต้องทำ method overloading สร้าง method หลาย ๆ ตัว เช่น
public void MyMethod(string name, string location) {
Console.WriteLine("Name is {0}, Location is {1}", name, location);
}
public void MyMethod(string name) {
MyMethod(name, "Bangkok");
}
แต่ Optional Parameter ทำให้เราเขียนแบบนี้ได้เลย
public void MyMethod(string name, string location = "Bangkok") {
Console.WriteLine("Name is {0}, Location is {1}", name, location);
}
COM Interoperability
การทำงานกับ COM เขียนง่ายขึ้น หลัก ๆ ก็มาจาก dynamic และ named parameters
และเพิ่มว่าไม่ต้องใส่ ref missing อีกต่อไป เช่น
obj.Foo(ref missing, ref missing, 
ref missing, ref missing,
5, ref missing,
ref missing, ref missing);
เป็น
obj.Foo(fooID: 5);
จะเห็นว่าเขียนง่ายขึ้นเยอะ

Co- and Contra-Variance
คือ การแปลง Type ของ Generic Type
ปกติ เราไม่สามารถ assign IEnumerable<string> ไปที่ IEnumerable<object> ได้
แต่ C# 4.0 ทำได้

มีข้อกำหนดนิดหน่อยว่า คุณไม่สามารถทำ Co-Variance และ Contra-Variance พร้อมกันได้
คุณสามารถทำ Co-Variance ในกรณีที่ Type นั้นเป็น output ของ Method เท่านั้น เช่น
IEnumerable<T> มี Method เดียวคือ IEnumerator<T> GetEnumerator() 
จะเห็นว่า T อยู่ในส่วนของ output ดังนั้นเราจึงทำ Co-Variance ได้
IEnumerable<string> เป็น IEnumerable<object> ได้

ส่วน Contra-Variance จะทำได้ในกรณี Type นั้นเป็น input ของ Method เท่านั้น เช่น
IComparer<T> มี Method เดียวคือ int Compare(T a, T b) 
จะเห็นว่า T อยู่ในส่วนของ input ดังนั้นเราจึงทำ Contra-Variance ได้
IComparer<object> เป็น IComparer<string> ได้

และมีกรณีที่ไม่สามารถทำทั้ง Co- และ Contra-Variance ได้
คือ Type นั้นเป็น Value Type เช่น IEnumerable<int> ไม่สามารถเป็น IEnumerable<object> ได้
อีกแบบคือ Type นั้นเป็นทั้ง Input และ Output ของ Method เช่น
List<T> มีทั้ง T List.get_Item(int a) และ void List.set_Item(int a, T item)
จะเห็นว่า T อยู่ทั้งในส่วนของ Input และ Output จึงไม่สามารถทำ Co- และ Contra-Variance ได้

และจะมีอะไรใน C# 5.0?
ใน Video จะมีปิดท้าย โชว์ Compiler as a Service ของ C# ถัดไปอีก
เหมือนกับ Eval ใน JavaScript ที่สามารถเขียน Code ด้วย string ได้ (ซึ่งมีเป็นชาติแล้ว)
ใน Video โชว์การทำ C# Shell ประมาณว่า เขียน Loop เขียน Function สร้าง Form จาก Shell ได้เลย

ถ้ามีเวลาว่างลองโหลดดูขำ ๆ ครับ ชั่วโมงกว่าเอง Smiley
โหลด ที่นี่

 

Create Date : 16 มีนาคม 2552
Last Update : 16 มีนาคม 2552 1:27:09 น.  

C# opensource project ผมเขียนเอง ช่วยทดสอบกันหน่อยครับ

เป็น Project เกี่ยวกับ เพิ่มความสามารถโดยทั่วไปของ C# ให้ทำงานได้ง่ายขึ้น
เป็น Code ที่รวบรวมจากการทำงาน และเขียนเล่นเองของผม
เดิมทีจะรวบรวมพวกนี้แหละ มาเขียนใน Bloggang (ดูบทความเก่า ๆ ได้)
แต่หลัง ๆ ชักเยอะ ขี้เกียจเขียนบทความ เลยทำเป็น opensource project ซะเลย Smiley
(ต่อไปที่จะเขียนใน Bloggang คงไม่มี code หนัก ๆ แล้ว คงเป็นบทความทั่วไป)

Project นี้ชื่อ Chaow Framework
host ไว้ที่ codeplex
หน้า project คลิกที่นี่



อธิบายคร่าว ๆ เกี่ยวกับ Project
Project นี้วางโครงการเขียนตอนนี้ 12 modules เสร็จไปแล้ว (2 modules ครึ่ง)
12 modules มีดังนี้
module คำอธิบาย
Chaow.Collections รวบรวม Class ต่าง ๆ ไว้จัดการพวก Collections
Chaow.Combinatoric รวบรวม Algorithms สำหรับทำ Combinatoric Search
Chaow.Expression ไว้จัดการพวก Expression
Chaow.Extensions รวบรวม Extension methods ล้วน ๆ
Chaow.Heuristic รวบรวม Algorithms สำหรับทำ Heuristic Search
Chaow.InterOp ใช้ทำพวก Add-on เอาไว้ทำให้ App เราสามารถเพิ่มเติมได้ โดยไม่ต้อง Compile ใหม่
Chaow.LINCON เขียน Constraint Programming ด้วย Linq
Chaow.LogicProgramming เขียน Logic Programming ด้วย C#
Chaow.Numeric รวบรวม Types และ Methods ต่าง ๆ เกี่ยวกับ Math
Chaow.Numeric.Analysis รวบรวม Algorithms สำหรับวิเคราะห์ Math ขั้นสูง
Chaow.Recreation รวบรวมพวก Games กับ Puzzles ต่าง ๆ
Chaow.Threading เอาไว้เขียน Multi-thread program

ที่เขียนเสร็จตอนนี้คือ Extensions กับ Numeric
และ Threading จะมีเพิ่มเติมอีก

ถ้า Download มาแล้วจะมี Sample Library ให้เล่น
ลอง Test แต่ละ method ดูได้ว่าทำงานยังไง
แล้วถ้าลองใช้จริงดู เจอ Bug หรือมี Issue หรือคำแนะนำต่าง ๆ
กรุณา comment ด้วยครับ

ขอบคุณครับ Smiley

 

Create Date : 10 มกราคม 2552
Last Update : 10 มกราคม 2552 0:35:45 น.  

ความสามารถลับ ๆ ที่คุณยังไม่รู้ใน C#

เอามาจาก stackoverflow.com นะครับ
ที่จริงอยากแปลไทยให้หมดเลย
แต่มีเยอะมากครับ
เลยเขียนย่อ ๆ ให้ก็แล้วกัน
อันไหนอยากให้อธิบายเพิ่มก็ถามได้ครับ

จริง ๆ ก็มี hidden features ของภาษาอื่น ๆ อีกเพียบเลยครับ
ลองกดเข้าไปดู

สรุปคร่าว ๆ นะครับ ถ้าผิดแย้งด้วยครับไม่ได้รู้ทุกอัน

กลุ่ม keyword

yield

method ที่เป็น IEnumerable จะสามารถคืนค่าได้มากกว่า 1 ค่า
yield return จะเป็นคำสั่งคืนค่าแต่ละค่า
ส่วน yield break จะเป็นคำสั่งหยุดการคืนค่า
(ดูตัวอย่างได้ที่ Post แรก และ Post ที่แล้ว)

var

คุณสามารถประกาศตัวแปรเป็น var แทนที่จะระบุ type ได้เลย
(บางคนคิดว่าประกาศตัวแปรเป็น var แล้วจะสูญเสีย performance จริง ๆ ไม่เสียนะครับ
compiler จะ resolve type ของตัวแปรให้ตั้งแต่ตอน compile)

using

เป็นคำสั่งตั้งชื่อ namespace ใหม่ หรือตั้งชื่อ class ใหม่
มีประโยชน์มากถ้าชื่อมันยาวมาก

readonly

คำสั่งประกาศ field ว่าอ่านได้อย่างเดียว
คุณสามารถกำหนดค่าของ field ที่เป็น readonly ได้ตอนที่ class กำลัง construct เท่านั้น
(readonly ไม่ทำให้ performance เพิ่ม แต่ทำให้มั่นใจว่า field นี้จะไม่โดนแก้ไข)

as

คำสั่งแปลง type ถ้า class นั้น compatible กับ type ที่จะแปลง
ถ้าผ่านจะได้ object ที่แปลง type แล้ว ถ้าไม่ผ่านจะได้ null
ไม่สามารถใช้กับ struct ได้ ใช้กับ class เท่านั้น

is

คำสั่งทดสอบว่า class นั้น compatible กับ type ที่จะทดสอบหรือเปล่า
ไม่สามารถใช้กับ struct ได้ ใช้กับ class เท่านั้น

default(T)

ถ้าใช้กับ type ที่เป็น class จะได้ null
ถ้าใช้กับ type ที่เป็น struct จะได้ 0 หรือค่าเริ่มต้นของ struct นั้น
ใช้ใน generic type ซึ่งเราไม่รู้ว่า type นั้นเป็น class หรือ struct

global::

เป็นการเรียก namespace ตั้งแต่ระดับ root ออกมา
ใช้ในกรณีตั้งชื่อ class ซ้ำกับ namespace เช่น System

using()

object ที่อยู่ในส่วนของ using จะ dispose อัตโนมัติเมื่อออกจาก block ของ using

volatile

ใช้กับ field เป็นการแจ้ง compiler ว่าไม่ต้อง optimize field นี้ในการอ่านข้อมูล
ใช้กับ field ที่โดนแก้ไขแบบ multi-thread และไม่โดน lock
เพื่อให้การอ่านข้อมูลได้ข้อมูลล่าสุดอยู่เสมอ

extern alias

เป็นคำสั่งเรียกใช้ namespace ที่ reference และตั้ง alias ไว้
ใช้ในกรณี Program มี reference library ประเภทเดียวไว้ 2 versions


กลุ่ม attribute

DefaultValue

ใช้ตอนสร้าง Custom Control เป็นการระบุว่า
Property นี้ ค่า Default Value คือเท่าไหร่

Obsolete

เป็นการแจ้ง compiler ว่า สิ่งที่คุณระบุว่า Obsolete
จะไม่มีใน version ถัดไปแล้ว ให้เลิกใช้ซะ
โดยสามารถกำหนดได้ว่าจะให้ขึ้นเตือน หรือบังคับให้ compile ไม่ผ่าน

DebuggerDisplay

ทำให้สิ่งที่คุณระบุ แสดงผลตอน Debug ตามที่คุณต้องการ
(ซึ่งโดยปกติค่าที่แสดงตอน Debug จะเอามาจาก method ชื่อ ToString)

DebuggerBrowsable

เป็นการระบุว่า คุณจะซ่อน Field หรือ Property ไหนตอน Debug

DebuggerStepThrough

เป็นการทำให้ Debugger ข้าม Class หรือ Method ที่คุณระบุตอนกำลัง Debug
(แต่คุณก็ยังสามารถตั้งค่า break point ใน Class หรือ Method นั้นได้)

ThreadStatic

เป็นการระบุ Static Field ที่กำหนดว่า จะมีค่าแยกกันแต่ละ Thread
ใช้เมื่อต้องการให้ Thread แต่ละ Thread เก็บข้อมูลแยกกัน

Flags

ใช้กับ enum เป็นการระบุว่า enum นั้นสามารถมีค่าเป็น combination ได้
เช่น FileAcces มี Read กับ Write และสามารถ set เป็น Read Or Write ได้
(อย่างไรก็ตามตอนระบุ enum คุณต้องตั้งค่าแต่ละอันให้เป็น 1,2,4,8,… ไปเรื่อย ๆ)

Conditional

ใช้กับ method กับ class เป็นการระบุว่า
ถ้าไม่ได้ DEFINE ชื่อ condition ตอน compile
ให้ยกเลิกการเรียก method หรือ class นั้นไปได้เลย


กลุ่ม syntax

??

ใช้หาค่าที่ไม่ใช่ Null อันแรก เช่น a ?? b ?? c
ถ้า a กับ b เป็น Null จะ return c

number flag

Decimal = M
Float = F
Double = D
Long = L
เช่น 30D เป็นการสร้างค่า double ที่มีค่า 30.0
(จริง ๆ แล้ว compiler ฉลาดพอที่จะแปลงค่า constant เป็น type เดียวกับที่เรากำลัง assign เช่น double d = 10;
10 ควรจะเป็น int แต่ตอน compile จะได้ 10.0D อัตโนมัติ ไม่เสีย Performance)

where T :

เป็นการจำกัด Generic Type โดยเติม keyword ด้านล่างต่อท้าย syntax
struct: Generic Type ต้องเป็น struct เท่านั้น
class: Generic Type ต้องเป็น class เท่านั้น
new(): Generic Type ต้องมี public constructor แบบไม่มี parameter
<Base Class>: Generic Type ต้องเป็น Type ที่ derived มาจาก base class ที่กำหนด
<Interface>: Generic Type ต้อง implement interface ที่กำหนด
U: Generic Type ต้อง Derived หรือ implement Type U (ในกรณีมี Type Parameter หลายตัว)

Type Inference

อันนี้เป็น feature ใหม่ C# 3.0
ปกติ method ที่เป็น generic ต้องกำหนด Type Parameter ด้วย
แต่ C# ใหม่ ถ้าคุณกำหนด Parameter ซึ่งระบุ Type นั้นแล้ว ก็ไม่ต้องระบุ Type Parameter
อ่าน Post เก่า เพิ่มเติม

Lambda

feature ใหม่ C# 3.0
เป็นการสร้าง anonymous method แบบสั้น ๆ
อ่าน Post เก่า เพิ่มเติม

Anonymous Type

feature ใหม่ C# 3.0
สร้าง Type แบบ Inline ไม่ต้องเสียเวลาเขียน class
อ่าน Post เก่า เพิ่มเติม

Object/Collection Initializer

feature ใหม่ C# 3.0
เป็นการ set property และ add items แบบ inline
อ่าน Post เก่า เพิ่มเติม

Auto Properties

feature ใหม่ C# 3.0
Post เก่าไม่ได้เขียนถึง เนื่องจากปกติเราต้องกำหนด field ให้ Property อยู่แล้ว
ใช้ Auto Properties ทำให้ไม่ต้องสร้าง field เช่น
public int Name { get; private set; }
จะเห็นว่าไม่ต้องอ้างถึง field หลัง Property Name
และ get กับ set ยังสามารถกำหนด scope ที่ต่างกันได้เหมือนเดิม

@ (string literals)

ปกติ string เรากำหนดอย่างนี้ “…”
แต่เราก็สามารถกำหนดอย่างนี้ก็ได้ @“…”
ต่างกันคือ แบบแรกจะมีรหัสต่าง ๆ เช่น n ขึ้นบรรทัดใหม่
แต่แบบที่ 2 ไม่ต้องมีรหัส จะเก็บ string ตามที่เราพิมพ์ทำให้อ่านง่าย
(เวลาจะ escape เครื่องหมายคำพูดใช้ “” เครื่องหมายคำพูด 2 ที)

enum underlining type

Type ประเภท enum สามารถกำหนด Type หลักได้ด้วยนะ
ถ้าไม่กำหนดจะเป็น int
โดยสามารถกำหนดเป็น number แบบต่าง ๆ เช่น byte, short, long (เฉพาะเลขจำนวนเต็ม)

@variable name

เราสามารถกำหนดชื่อ variable/class หรืออะไรก็ตามแต่
ที่ซ้ำกับ keyword ของ C# ได้ เช่น object โดยต้องมี @นำหน้า เช่น @object
โดยเวลา reflect ออกมาจะได้ชื่อนั้นแบบไม่มี @

event

C# มี event ด้วยนะ หลายคนไม่รู้
เราสามารถ subscribe และ unsubscribe event ได้
และสามารถกำหนด code ตอน add/remove event ได้
(ลองหาข้อมูลเอาเอง มันเยอะมาก)

string format

เราสามารถ format ให้แสดงวงเล็บปีกกาได้ ดูตามตัวอย่างเลยครับ
int foo = 3;
string bar = 'blind mice';
String.Format('{{i am in brackets!}} {0} {1}', foo, bar);
//outputs '{i am in brackets!} 3 blind mice'

? :

Conditional Operator สะดวก เวลาจะเขียน if else แล้วกำหนดค่า เช่น
int foo = (trueOrFalse) ? 1 : 2;


อูย... เหนื่อยหรือยังครับ  ผมเริ่มเหนื่อยละ นี่แค่สรุปนะเนี่ย Smiley

จริง ๆ มีอีกเยอะนะ ขี้เกียจทำละ (ตกม้าตายซะงั้น Smiley )
ตามไปอ่านที่ stackoverflow.com ละกัน

ที่ยังไม่ได้เขียน ขอสรุปอันที่แจ๋ว ๆ ละกัน
- C# มี keyword พิเศษที่ไม่ได้บอกใคร คือ __makeref __reftype __refvalue กะ __arglist (ใช้ทำไรผมก็ไม่รู้)
- คุณสามารถทำ partial method ได้นะ (ประกาศ method file นึง, แล้วเขียน method อีก file นึง)
- คุณสามารถ overload true กะ false ได้นะ (ใช้กำหนดว่าเมื่อไหร่ evaluate เป็น true หรือ false)
- คุณสามารถทำ weakreference ได้ (ใช้ใน program ที่ใช้ resource เยอะ ๆ เช่น tree list ตอนเลิกใช้ก็กำหนดเป็น weakref. แทนที่จะทำลาย เมื่อกลับมาใช้ใหม่ถ้าใช้ทันก่อนโดนทำลาย ก็ไม่ต้องสร้างใหม่)
- ใช้ list.ForEach เร็วกว่าใช้ foreach statement (ไม่เชื่ออะเด่ะ ต้องลอง)
- compare string ใช้ตัวใหญ่เร็วกว่าใช้ตัวเล็ก เช่น s.ToUpper() == "HELLO" เร็วกว่า s.Lower() == "hello" (จริงอ่ะ ?)
- ปกติ anonymous type ใช้ในระดับ class ไม่ได้ใช่มะ แต่มี technic ที่ทำให้ใช้ได้ (ตามไปอ่านเอาเอง)
- มีวิธีทำให้ assembly นึง ประกอบด้วยภาษามากกว่า 1 ภาษาได้ เช่นใน team มีถนัด vb กะ c# ก็แยกกันเขียนแล้วมารวมกัน (ทำไง ?)
- มีวิธีทำให้ .NET 2.0 ซึ่งไม่มี LINQ ใช้ LINQ ได้ (นั่นดิ ทำไง?)
- Parallel Linq ออกเป็น CTP ละ เขียน Linq ธรรมดาแต่ Process แบบ Multi-Thread ได้เลยนะ ไม่ต้องเขียนเอง

สุดท้ายเพิ่มเติมอีกนิดหน่อย นอกเหนือจากใน stackoverflow
- .NET มีออก Package ใหม่ชื่อ Azure ยก SQLServer, WCF, WFF ไป host บน web เฉยเลย
- และ C# ออก spec version 4.0 แล้ว ภาษาเริ่มหลุดโลกขึ้นทุกที

หัวแตกละ...จบ Smiley

 

Create Date : 13 ธันวาคม 2551
Last Update : 13 ธันวาคม 2551 1:19:53 น.  

1  2  3  4  

chaowman

Location :
กรุงเทพฯ Thailand

[Profile ทั้งหมด]


My FriendFlock
ฝากข้อความหลังไมค์
Rss Feed [?]



 
Group Blog

 
All Blogs

 
Friends' blogs
[Add chaowman's blog to your weblog]
Links
 

 

 

Pantip-Cafe | Pantip-TechExchange | PantipMarket.com | Pantown.com | © 2004 BlogGang.com allrights reserved.