Mungkin untuk mendeklarasikan fungsi lambda dan segera menyebutnya:
Func<int, int> lambda = (input) => { return 1; };
int output = lambda(0);
Saya bertanya-tanya apakah mungkin untuk melakukannya dalam satu baris, misalnya sesuatu seperti
int output = (input) => { return 1; }(0);
yang memberikan kesalahan kompilator "Nama metode yang diharapkan". Casting untuk Func<int, int>
tidak bekerja:
int output = (Func<int, int>)((input) => { return 1; })(0);
memberikan kesalahan yang sama, dan untuk alasan yang disebutkan di bawah ini saya ingin menghindari keharusan untuk secara eksplisit menentukan jenis argumen input (yang pertama int
).
Anda mungkin bertanya - tanya mengapa saya ingin melakukan ini, daripada hanya menyematkan kode secara langsung, misalnya int output = 1;
. Alasannya adalah sebagai berikut: Saya telah membuat referensi untuk layanan web dengan SOAP svcutil
, yang karena elemen bersarang menghasilkan nama kelas yang sangat panjang, yang saya ingin hindari mengetik. Jadi, bukannya
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = CreateAddress(sh.ReceiverAddress_Shipment);
}).ToArray()
};
dan CreateAddress(GetOrderResultOrderShipment_OrderShipmentShipment_Address address)
metode yang terpisah (nama asli bahkan lebih lama, dan saya memiliki kontrol yang sangat terbatas tentang formulir), saya ingin menulis
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = sh.ReceiverAddress_Shipment == null ? null : () => {
var a = sh.ReceiverAddress_Shipment.Address;
return new Address {
Street = a.Street
...
};
}()
}).ToArray()
};
Saya tahu saya bisa menulis
Address = sh.ReceiverAddress_Shipment == null ? null : new Address {
Street = sh.ReceiverAddress_Shipment.Address.Street,
...
}
tetapi bahkan itu ( sh.ReceiverAddress_Shipment.Address
bagian) menjadi sangat berulang jika ada banyak bidang. Mendeklarasikan lambda dan segera menyebutnya akan lebih elegan untuk menulis karakter.
int output = ((Func<int>) (() => { return 1; }))();
public T Exec<T>(Func<T> func) => return func();
dan gunakan seperti ini:int x = Exec(() => { return 1; });
Bagi saya itu jauh lebih bagus daripada casting dengan semua parensnya.Jawaban:
Alih-alih mencoba melemparkan lambda, saya sarankan Anda menggunakan fungsi pembantu kecil:
yang kemudian bisa menggunakan seperti ini:
int x = Exec(myVar => myVar + 2, 0);
. Bagi saya ini jauh lebih baik daripada alternatif yang disarankan di sini.sumber
Itu jelek, tapi itu mungkin:
Anda dapat memilih, tetapi lambda harus dimasukkan dalam tanda kurung.
Di atas dapat disederhanakan juga:
sumber
int output = (Func<int>)(() => { return 1; })();
tetapi para pemain memiliki prioritas lebih rendah daripada eksekusi lambda.Literatur Lambda dalam bahasa C # memiliki perbedaan yang aneh karena artinya tergantung pada jenisnya. Mereka pada dasarnya kelebihan beban pada tipe pengembalian mereka yang merupakan sesuatu yang tidak ada di tempat lain di C #. (Numerik literal agak mirip.)
The persis sama lambda literal dapat baik mengevaluasi fungsi anonim yang Anda dapat mengeksekusi (yaitu
Func
/Action
) atau representasi abstrak dari operasi dalam Tubuh, jenis seperti Abstrak Sintaks Pohon (yaitu LINQ Ekspresi Pohon).Yang terakhir adalah, misalnya, bagaimana LINQ to SQL, LINQ to XML, dll bekerja: lambda tidak mengevaluasi ke kode yang dapat dieksekusi, mereka mengevaluasi ke Pohon Ekspresi LINQ, dan penyedia LINQ kemudian dapat menggunakan Pohon Ekspresi untuk memahami apa yang tubuh lambda sedang melakukan dan menghasilkan misalnya SQL Query dari itu.
Dalam kasus Anda, tidak ada cara bagi kompiler untuk mengetahui apakah literal lambda seharusnya dievaluasi ke
Func
atau Ekspresi LINQ. Itulah sebabnya jawaban Johnathan Barclay bekerja: ia memberikan tipe pada ekspresi lambda dan oleh karena itu, kompiler tahu bahwa Anda menginginkanFunc
kode yang dikompilasi yang mengeksekusi tubuh lambda Anda alih-alih Pohon Ekspresi LINQ yang tidak dievaluasi yang mewakili kode di dalamnya tubuh lambda.sumber
Anda dapat menguraikan deklarasi
Func
dengan melakukandan segera memintanya.
sumber
Anda juga dapat membuat alias dalam
Select
metode iniatau dengan
??
operatorsumber
Jika Anda tidak keberatan melanggar beberapa pedoman desain metode ekstensi, metode ekstensi yang dikombinasikan dengan operator kondisi-nol
?.
dapat membawa Anda cukup jauh:akan memberi Anda ini:
dan jika Anda sebagian besar membutuhkan array, maka ganti
ToArray
metode ekstensi untuk merangkum beberapa metode panggilan lagi:yang menghasilkan:
sumber