Apakah ada cara untuk menentukan ekspresi C # lambda yang "kosong"?

118

Saya ingin menyatakan ekspresi lambda "kosong" yang tidak berarti apa-apa. Adakah cara untuk melakukan sesuatu seperti ini tanpa memerlukan DoNothing()metode?

public MyViewModel()
{
    SomeMenuCommand = new RelayCommand(
            x => DoNothing(),
            x => CanSomeMenuCommandExecute());
}

private void DoNothing()
{
}

private bool CanSomeMenuCommandExecute()
{
    // this depends on my mood
}

Maksud saya melakukan ini hanya mengontrol status diaktifkan / dinonaktifkan dari perintah WPF saya, tetapi itu di samping. Mungkin masih terlalu pagi bagi saya, tetapi saya membayangkan pasti ada cara untuk menyatakan x => DoNothing()ekspresi lambda dengan cara seperti ini untuk mencapai hal yang sama:

SomeMenuCommand = new RelayCommand(
    x => (),
    x => CanSomeMenuCommandExecute());

Apakah ada cara untuk melakukan ini? Sepertinya tidak perlu metode tidak melakukan apa-apa.

rampok
sumber

Jawaban:

231
Action doNothing = () => { };
Rauhotz
sumber
Apakah ada lambda kosong yang telah ditentukan sebelumnya? Saya pikir itu adalah kinerja ide yang buruk untuk membuat lambda kosong setiap kali saya membutuhkannya. Misalnya di JQuery adanoop dan saya mengharapkan sesuatu yang mirip akan hadir di C #.
qqqqqqq
Jadi, apakah versi asinkron ini memerlukan verbose Func<Task> doNothing = async() => await Task.CompletedTask;?
Patrick Szalapski
23

Ini adalah pertanyaan lama, tetapi saya pikir saya akan menambahkan beberapa kode yang menurut saya berguna untuk situasi seperti ini. Saya memiliki Actionskelas statis dan Functionskelas statis dengan beberapa fungsi dasar di dalamnya:

public static class Actions
{
  public static void Empty() { }
  public static void Empty<T>(T value) { }
  public static void Empty<T1, T2>(T1 value1, T2 value2) { }
  /* Put as many overloads as you want */
}

public static class Functions
{
  public static T Identity<T>(T value) { return value; }

  public static T0 Default<T0>() { return default(T0); }
  public static T0 Default<T1, T0>(T1 value1) { return default(T0); }
  /* Put as many overloads as you want */

  /* Some other potential methods */
  public static bool IsNull<T>(T entity) where T : class { return entity == null; }
  public static bool IsNonNull<T>(T entity) where T : class { return entity != null; }

  /* Put as many overloads for True and False as you want */
  public static bool True<T>(T entity) { return true; }
  public static bool False<T>(T entity) { return false; }
}

Saya yakin ini sedikit membantu meningkatkan keterbacaan:

SomeMenuCommand = new RelayCommand(
        Actions.Empty,
        x => CanSomeMenuCommandExecute());

// Another example:
var lOrderedStrings = GetCollectionOfStrings().OrderBy(Functions.Identity);
Anthony
sumber
10

Ini harus bekerja:

SomeMenuCommand = new RelayCommand(
    x => {},
    x => CanSomeMenuCommandExecute());
Joseph
sumber
7

Dengan asumsi Anda hanya membutuhkan delegasi (bukan pohon ekspresi) maka ini harus berfungsi:

SomeMenuCommand = new RelayCommand(
        x => {},
        x => CanSomeMenuCommandExecute());

(Itu tidak akan bekerja dengan pohon ekspresi karena memiliki badan pernyataan . Lihat bagian 4.6 dari spesifikasi C # 3.0 untuk lebih jelasnya.)

Jon Skeet
sumber
2

Saya tidak sepenuhnya mengerti mengapa Anda membutuhkan metode DoNothing.

Tidak bisakah Anda melakukan:

SomeMenuCommand = new RelayCommand(
                null,
                x => CanSomeMenuCommandExecute());
Jorge Córdoba
sumber
3
Itu mungkin dicentang dan mungkin akan melempar NRE.
Dykam
Saya pikir Dykam benar, tetapi saya hanya tidak berpikir untuk memberikan null :-)
Rob
1
Saya tidak mengerti mengapa ini tidak disukai? Jorge membuat poin yang valid, meskipun itu akan menjadi upaya kecil untuk memeriksanya.
Cohen
+1, ini adalah solusi yang valid, hanya saja pemeriksaan nol harus diperpanjang new RelayCommand(...
nawfal