เมื่อรวบรวมแล้วจะมีความแตกต่างระหว่าง:
delegate { x = 0; }
และ
() => { x = 0 }
?
เมื่อรวบรวมแล้วจะมีความแตกต่างระหว่าง:
delegate { x = 0; }
และ
() => { x = 0 }
?
คำตอบ:
คำตอบสั้น ๆ : ไม่
คำตอบอีกต่อไปที่อาจไม่เกี่ยวข้อง:
Func
หรือAction
) คุณจะได้รับผู้แทนแบบไม่ระบุชื่อแก้ไข: นี่คือลิงค์สำหรับ Expressions
ฉันชอบคำตอบของ Amy แต่ฉันคิดว่าฉันอวดความสามารถ คำถามบอกว่า "เมื่อรวบรวมแล้ว" - ซึ่งแสดงให้เห็นว่าทั้งสองสำนวนได้รับการรวบรวม พวกเขาจะรวบรวมได้อย่างไร แต่มีใครถูกเปลี่ยนให้เป็นผู้รับมอบสิทธิ์และอีกคนหนึ่งเป็นต้นไม้แสดงออก? มันเป็นเรื่องยาก - คุณต้องใช้คุณสมบัติอื่นของวิธีการที่ไม่ระบุชื่อ อันเดียวที่ไม่ได้แบ่งปันโดยการแสดงออกแลมบ์ดา หากคุณระบุวิธีที่ไม่ระบุชื่อโดยไม่ได้ระบุรายการพารามิเตอร์เลยมันจะเข้ากันได้กับประเภทตัวแทนที่ส่งคืนเป็นโมฆะและไม่มีout
พารามิเตอร์ใด ๆ ด้วยความรู้นี้เราควรจะสามารถสร้างสองเกินพิกัดเพื่อให้การแสดงออกอย่างสมบูรณ์โปร่งใส แต่แตกต่างกันมาก
แต่เกิดภัยพิบัติ! อย่างน้อยด้วย C # 3.0 คุณไม่สามารถแปลงนิพจน์แลมบ์ดาที่มีเนื้อความบล็อกเป็นนิพจน์ได้และคุณไม่สามารถแปลงนิพจน์แลมบ์ดาด้วยการกำหนดค่าในร่างกาย (แม้ว่าจะใช้เป็นค่าส่งคืน) สิ่งนี้อาจเปลี่ยนแปลงด้วย C # 4.0 และ. NET 4.0 ซึ่งอนุญาตให้แสดงได้มากขึ้นในทรีนิพจน์ ดังนั้นในคำอื่น ๆ ที่มีตัวอย่าง MojoFilter ที่เกิดขึ้นเพื่อให้ทั้งสองจะเกือบเสมอถูกแปลงเป็นสิ่งเดียวกัน (รายละเอียดเพิ่มเติมในหนึ่งนาที)
เราสามารถใช้เคล็ดลับพารามิเตอร์ผู้มอบหมายหากเราเปลี่ยนร่างกายเล็กน้อย:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
int x = 0;
Foo( () => x );
Foo( delegate { return x; } );
}
static void Foo(Func<int, int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
static void Foo(Expression<Func<int>> func)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
แต่เดี๋ยวก่อน! เราสามารถแยกความแตกต่างระหว่างทั้งสองได้โดยไม่ต้องใช้ต้นไม้แสดงออกถ้าเราฉลาดแกมโกงมากพอ ตัวอย่างด้านล่างใช้กฎการแก้ปัญหาการโอเวอร์โหลด (และเคล็ดลับการจับคู่ผู้ร่วมประชุมโดยไม่ระบุชื่อ) ...
using System;
using System.Linq.Expressions;
public class Base
{
public void Foo(Action action)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
public class Derived : Base
{
public void Foo(Action<int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
int x = 0;
d.Foo( () => { x = 0; } );
d.Foo( delegate { x = 0; } );
}
}
อุ๊ยตาย จำเด็ก ๆ ทุกครั้งที่คุณใช้วิธีมากไปจากคลาสพื้นฐานลูกแมวตัวน้อยจะเริ่มร้องไห้
delegate { ... }
เป็นไม่ได้เช่นเดียวกับdelegate() { ... }
- หลังเป็นเพียงเข้ากันได้กับประเภท parameterless ผู้ร่วมประชุม
ในสองตัวอย่างข้างต้นไม่มีความแตกต่างศูนย์
การแสดงออก:
() => { x = 0 }
เป็นนิพจน์แลมบ์ดาที่มีเนื้อหาคำสั่งดังนั้นจึงไม่สามารถรวบรวมเป็นต้นไม้การแสดงออกได้ ในความเป็นจริงมันไม่ได้คอมไพล์เพราะมันต้องการอัฒภาคหลังจาก 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B ถูกต้อง โปรดทราบว่าอาจมีข้อได้เปรียบในการใช้ทรีนิพจน์ LINQ ไปยัง SQL จะตรวจสอบแผนผังนิพจน์และแปลงเป็น SQL
นอกจากนี้คุณยังสามารถเล่นลูกเล่นกับ lamdas และ tree expression เพื่อส่งชื่อของสมาชิกคลาสไปยังเฟรมเวิร์กได้อย่างมีประสิทธิภาพด้วยวิธีที่ปลอดภัย Moqเป็นตัวอย่างของสิ่งนี้
มีความแตกต่าง
ตัวอย่าง:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
และฉันแทนที่ด้วยแลมบ์ดา: (ผิดพลาด)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
พื้นฐานบางอย่างที่นี่
นี่เป็นวิธีที่ไม่ระบุชื่อ
(string testString) => { Console.WriteLine(testString); };
เนื่องจากวิธีการที่ไม่ระบุชื่อไม่มีชื่อเราจึงต้องมีผู้รับมอบสิทธิ์ซึ่งเราสามารถกำหนดวิธีหรือนิพจน์เหล่านี้ได้ เช่น
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
เช่นเดียวกันกับการแสดงออกแลมบ์ดา โดยปกติแล้วเราต้องการผู้ร่วมงานเพื่อใช้พวกเขา
s => s.Age > someValue && s.Age < someValue // will return true/false
เราสามารถใช้ตัวแทน func เพื่อใช้การแสดงออกนี้
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);