Pintasan untuk membuat daftar item tunggal dalam C #


134

Di C #, apakah ada jalan pintas sebaris untuk instantiate Daftar <T> dengan hanya satu item.

Saya sedang melakukan:

new List<string>( new string[] { "title" } ))

Memiliki kode ini di mana-mana mengurangi keterbacaan. Saya sudah memikirkan menggunakan metode utilitas seperti ini:

public static List<T> SingleItemList<T>( T value )
{
    return (new List<T>( new T[] { value } ));
}

Jadi saya bisa melakukan:

SingleItemList("title");

Apakah ada cara yang lebih pendek / bersih?

Terima kasih.

Jawaban:


245

Cukup gunakan ini:

List<string> list = new List<string>() { "single value" };

Anda bahkan dapat menghilangkan tanda kurung ():

List<string> list = new List<string> { "single value" };

Pembaruan: tentu saja ini juga berfungsi untuk lebih dari satu entri:

List<string> list = new List<string> { "value1", "value2", ... };

5
menempatkan 1 literal dalam tanda kurung dari opsi pertama, sehingga penyimpanan untuk tepat satu ruang dialokasikan daripada standar 10
Joel Coehoorn

5
Default akhirnya menjadi 4, saya percaya: Daftar baru <string> {"Hello"} .Capacity == 4
Jon Skeet

39
var list = new List<string>(1) { "hello" };

Sangat mirip dengan apa yang diposkan orang lain, kecuali bahwa itu memastikan untuk hanya mengalokasikan ruang untuk item tunggal pada awalnya.

Tentu saja, jika Anda tahu Anda akan menambahkan banyak barang nanti mungkin itu bukan ide yang baik, tetapi masih perlu disebutkan sekali.


Kapasitas diatur ke satu. Saya memilih empat jawaban pada halaman ini termasuk kedua Jon Skeet tetapi saya menganggap ini sebagai yang paling benar.
The Lonely Coder

28

Gagasan Michael untuk menggunakan metode ekstensi mengarah ke sesuatu yang lebih sederhana:

public static List<T> InList<T>(this T item)
{
    return new List<T> { item };
}

Jadi Anda bisa melakukan ini:

List<string> foo = "Hello".InList();

Saya tidak yakin apakah saya suka atau tidak, keberatan Anda ...


1
Saya juga tidak yakin saya menyukainya: bukankah ini ekstensi "aneh" dari tipe string (misalnya)?
M4N

1
Saya belum berhasil ke metode ekstensi dalam buku Anda, Jon :-) Ini sepertinya agak aneh, tapi saya suka utilitas itu. Terima kasih Martin dan Jon.
Ryan Ische

2
@ Martin: Ini adalah ekstensi aneh dari setiap jenis. Ini umumnya tidak dianjurkan, tetapi ini adalah ide umum yang menarik.
Jon Skeet

4
Ini memiliki beberapa penggunaan bahasa spesifik domain internal, terutama dengan jenis nilai. Ambil contoh: clock.AlertUser.In (1.Minute) membaca jauh lebih baik daripada clock.AlertUser (TimeSpan.FromMinutes (1));
Michael Meadows

17

Jawaban berbeda dari jawaban saya sebelumnya, berdasarkan paparan ke Google Java Collections :

public static class Lists
{
    public static List<T> Of<T>(T item)
    {
        return new List<T> { item };
    }
}

Kemudian:

List<string> x = Lists.Of("Hello");

Saya menyarankan untuk memeriksa GJC - ada banyak hal menarik di dalamnya (Secara pribadi saya akan mengabaikan tag "alpha" - itu hanya versi open source yang "alpha" dan didasarkan pada API internal yang sangat stabil dan banyak digunakan) .)



7

Gunakan metode ekstensi dengan metode chaining.

public static List<T> WithItems(this List<T> list, params T[] items)
{
    list.AddRange(items);
    return list;
}

Ini akan membuat Anda melakukan ini:

List<string> strings = new List<string>().WithItems("Yes");

atau

List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So");

Memperbarui

Anda sekarang dapat menggunakan inisialisasi daftar:

var strings = new List<string> { "This", "That", "The Other" };

Lihat http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx


Mungkin ini karena versi C # yang lebih baru sejak 2009, tapi saya merasa new List<string> {"Yes"}lebih baik ...?
ErikE

@ErikE Menurut dokumentasi Microsoft ( msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx ) ini didukung di Visual Studio 2008. Saya tidak ingat sejauh itu untuk mengatakan secara pasti jika Saya terlalu rumit pada saat itu. Memperbarui.
Michael Meadows

7

Namun cara lain, ditemukan di "C # /. Net Little wonders" (sayangnya, situs tidak ada lagi):

Enumerable.Repeat("value",1).ToList()

Membingungkan tapi pintar.
PRMan

4

Untuk satu item yang dapat dihitung dalam java adalah Collections.singleton ("string");

Dalam c # ini akan lebih efisien daripada Daftar baru:

public class SingleEnumerator<T> : IEnumerable<T>
{
    private readonly T m_Value;

    public SingleEnumerator(T value)
    {
        m_Value = value;
    }

    public IEnumerator<T> GetEnumerator()
    {
        yield return m_Value;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        yield return m_Value;
    }
}

tetapi apakah ada cara yang lebih sederhana menggunakan framework?


Itu sebenarnya jawaban terbaik menurut saya. Ini adalah pola yang sangat umum untuk memiliki daftar item tunggal, untuk mengurangi ukuran alokasi. Jika Anda sudah mencari jalan pintas Anda mungkin juga menggabungkan yang nyaman dengan yang baik.
Alex


2

Saya punya fungsi kecil ini:

public static class CoreUtil
{    
    public static IEnumerable<T> ToEnumerable<T>(params T[] items)
    {
        return items;
    }
}

Karena tidak menentukan jenis pengembalian beton, ini sangat umum sehingga saya menggunakannya di semua tempat. Kode Anda akan terlihat seperti

CoreUtil.ToEnumerable("title").ToList();

Tapi tentu saja itu juga memungkinkan

CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray();

Saya sering menggunakannya ketika saya harus menambahkan / menambahkan satu item ke output dari pernyataan LINQ. Misalnya menambahkan item kosong ke daftar pilihan:

CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name))

Menghemat beberapa ToList()dan Addpernyataan.

(Jawaban terlambat, tetapi saya menemukan oldie ini dan berpikir ini bisa membantu)



2

Terinspirasi oleh jawaban lain (dan jadi saya dapat mengambilnya kapan pun saya membutuhkannya!), Tetapi dengan penamaan / gaya yang selaras dengan F # (yang memiliki singletonfungsi standar per struktur data *):

namespace System.Collections.Generic
{
    public static class List
    {
        public static List<T> Singleton<T>(T value) => new List<T>(1) { value };
    }
}

* kecuali untuk ResizeArraydirinya sendiri tentu saja, maka pertanyaan ini :)


Dalam praktiknya saya benar-benar menamakannya Createuntuk menyelaraskan dengan pembantu lain yang saya definisikan seperti Tuple.Create, Lazy.Create[2], LazyTask.Createdll:

namespace System.Collections.Generic
{
    public static class List
    {
        public static List<T> Create<T>(T value) => new List<T>(1) { value };
    }
}

[2]

namespace System
{
    public static class Lazy
    {
        public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory);
    }
}

Terima kasih! Solusi saya juga. Beberapa hal: (1) implementasi daftar Anda tidak bersifat publik, sehingga tidak dapat digunakan di luar majelis deklarasi, dan (2) apa tujuan memasukkan ini ke dalam namespace Sistem?
Codure

@StephenRobinson alasan untuk memasukkan Lazyekstensi Systemadalah karena Lazyitu sendiri ada di System[dan karenanya Createakan muncul dalam daftar compleiton tanpa a using]. Tidak ada yang bisa diperoleh dari memaksa orang ke opennamespace yang berbeda? Menjadikan hal lain sebagai pribadi tidak disengaja; diperbaiki
Ruben Bartelink

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.