C # 'da tek öğe listesi oluşturma kısayolu


134

C # 'da, bir Listeyi <T> başlatmak için yalnızca bir öğeyle satır içi kısayol var mı?

Şu anda yapıyorum:

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

Bu kodun her yerde bulunması okunabilirliği azaltır. Ben böyle bir yardımcı yöntem kullanmayı düşündüm:

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

Böylece yapabilirim:

SingleItemList("title");

Daha kısa / daha temiz bir yol var mı?

Teşekkürler.

Yanıtlar:


245

Sadece şunu kullanın:

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

() Parantezlerini bile atlayabilirsiniz:

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

Güncelleme: tabii ki bu birden fazla giriş için de çalışır:

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

5
ilk seçeneğin parantezlerine 1 değişmez değer koyun, böylece varsayılan 10 yerine tam olarak bir alan için depolama ayrılır
Joel Coehoorn

5
Varsayılan 4 olur, inanıyorum: yeni Liste <string> {"Merhaba"} .Kapasite == 4
Jon Skeet

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

Başlangıçta yalnızca tek bir öğe için yer ayırmayı sağlamak dışında, diğerlerinin gönderdiklerine çok benzer.

Tabii ki, daha sonra bir sürü şey ekleyeceğinizi biliyorsanız, iyi bir fikir olmayabilir, ancak yine de bir kez bahsetmeye değer.


Kapasite bire ayarlı. Jon Skeet'in her ikisi de dahil olmak üzere bu sayfada dört cevaba oy verdim, ancak bunun en doğru olduğunu düşünüyorum.
Yalnız Kodlayıcı

28

Michael'ın uzatma yöntemlerini kullanma fikri daha da basit bir şeye yol açar:

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

Böylece bunu yapabilirsiniz:

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

Sevip sevmediğimden emin değilim, dikkat et ...


1
Ben de sevdim emin değilim: Bu dize türü (örneğin) "garip" bir uzantısı değil mi?
M4N

1
Henüz kitabınızda uzatma yöntemlerini yapmadım, Jon :-) Bu biraz garip görünüyor, ama faydasını seviyorum. Teşekkürler Martin ve Jon.
Ryan Ische

2
@ Martin: Her türden garip bir uzantı . Bu genellikle önerilmez, ancak ilginç bir genel fikirdir.
Jon Skeet

4
Özellikle değer türleriyle, alan adına özgü bazı dil kullanımlarına sahiptir. Örneğin: clock.AlertUser.In (1.Minute), clock.AlertUser (TimeSpan.FromMinutes (1)) 'den çok daha iyi okur;
Michael Meadows

17

Google Java Koleksiyonlarına maruz kalmama dayalı olarak öncekime farklı bir cevap :

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

Sonra:

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

GJC'yi kontrol etmenizi öneririm - içinde çok ilginç şeyler var. .)



7

Yöntem zincirleme ile bir genişletme yöntemi kullanın.

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

Bu, bunu yapmanıza izin verir:

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

veya

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

Güncelleme

Artık liste başlatıcıları kullanabilirsiniz:

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

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


Belki bu 2009 yılından bu yana C # daha yeni sürümleri nedeniyle, ama new List<string> {"Yes"}daha iyi buluyorum ...?
ErikE

@ErikE Microsoft belgelerine göre ( msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx ) bu, Visual Studio 2008'de desteklenmiştir. O zaman bunu çok karmaşık hale getirdim. Güncelleniyor.
Michael Meadows

7

"C # /. Net Little harikaları" üzerinde bulunan başka bir yol (ne yazık ki, site artık mevcut değil):

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

Kafa karıştırıcı ama akıllı.
PRMan

4

Java'da numaralandırılabilen tek bir öğe için Collections.singleton ("string");

C # 'da bu yeni bir Listeden daha verimli olacaktır:

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;
    }
}

ancak çerçeveyi kullanmanın daha basit bir yolu var mı?


Aslında bence en iyi cevap bu. Tek bir öğe listesine sahip olmak, ayırma boyutunu azaltmak çok yaygın bir kalıptır. Zaten bir kısayol arıyorsanız, uygun olanı iyi ile birleştirebilirsiniz.
Alex


2

Bu küçük işleve sahibim:

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

Somut bir geri dönüş tipi reçete etmediği için, o kadar genel ki, her yerde kullanıyorum. Kodunuz şöyle görünür

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

Ama tabii ki

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

Bir LINQ deyiminin çıktısına bir öğe eklemek / eklemek zorunda kaldığımda sıklıkla kullanırım. Örneğin, seçim listesine boş bir öğe eklemek için:

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

Birkaç kaydeder ToList()ve Addifadeler.

(Geç cevap, ama bu ihtiyar tökezledi ve bunun yararlı olabileceğini düşündüm)



2

Diğer cevaplardan esinlenerek (ve ihtiyaç duyduğumda alabilirim!), Ancak adlandırma / stil ile F # ( singletonveri yapısı başına standart bir işleve sahiptir) ile hizalanmış :

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

* ResizeArrayTabii ki kendisi hariç , bu yüzden bu soru :)


Pratikte ben aslında Adını Createben gibi tanımlayan diğer yardımcıları uyum sağlamak Tuple.Create, Lazy.Create[2], LazyTask.Createvb:

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);
    }
}

Teşekkürler! Benim çözümüm de. Birkaç şey: (1) liste uygulamanız herkese açık değil, bu yüzden ilan eden meclisin dışında kullanılamaz ve (2) bunları Sistem ad alanına doldurmanın amacı nedir?
Kod

Koymak için @StephenRobinson nedeni Lazyuzantıyı Systemolmasıdır Lazykendisinde bulunmadığı System[dolayısıyla ve Createbir olmadan compleiton listelerinde görünür using]. İnsanları farklı openbir ad alanına zorlamaktan kazanılacak bir şey yok mu? Diğerini özel yapmak kasıtlı değildi; sabit
Ruben Bartelink

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.