C # 'da boş bir diziyi nasıl başlatırım?


328

Boyutu belirtmeden boş bir dizi oluşturmak mümkün müdür?

Örneğin, ben yarattım:

String[] a = new String[5];

Yukarıdaki dize dizisini boyut olmadan oluşturabilir miyiz?


2
stackoverflow.com/questions/151936/… u bu bağlantıyı kontrol edin, dizi şeylerini net bir şekilde anlamanıza yardımcı olabilir
Ravi Gadag

Yanıtlar:


435

Önceden boyutunu bilmediğiniz bir koleksiyon kullanacaksanız, dizilerden daha iyi seçenekler vardır.

Bir kullan List<string>sen, çağrıyı bir dizi dönmek gerekirse ihtiyaç olarak birçok öğeleri olarak eklemek sağlayacak ve - yerine ToArray()değişkeni.

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

Eğer varsa gereken boş bir dizi oluşturmak bunu yapabilirsiniz:

string[] emptyStringArray = new string[0]; 

1
@Oded - string [] emptyStringArray = yeni dize [0]; boş bir diziye neden olmaz, değil mi? Bir öğenin boş olduğu bir öğeye sahip bir dizi gibi görünüyor.
rory.ap

11
@roryap - Hayır string[]. Hiçbir elemanı olmayan bir sonuç verir . Eğer erişmeye çalışırsanız emptyStringArray[0], birIndexOutOfRangeException
Oded

@Oded - Teşekkürler, C # için oldukça yeniyim. VB'de, sağlanan indeks elemanların sayısı değil, üst sınırdır.
rory.ap

1
Neyi daha iyi düşünürdünüz: var strings = new string [] {}; veya var dizeleri = yeni dize [0]; BTW: Boş bir diziyi yöntem parametreleri için mükemmel geçerli bir varsayılan olarak görüyorum: public void EditItems (IEnumerable <Item> toEdit, IEnumerable <long> toDelete = new long [] {})
realbart

6
@ RickO'Shea - C ++, C # değildir. Stroustrup C ++ 'sını biliyor - C # ve .NET GC'sini bildiğinden emin değil. Seninle dini bir savaşa girmeyeceksin.
Oded

181

Bunu dene:

string[] a = new string[] { };

7
Bu yanıtı genişleterek, boyutu OR türünü belirtmeden öğeleri içeren diziyi başlatabilirsiniz, derleyici başlatıcıdan çıkarım yapar: var a = new [] {"a", "b", "c"}; Bu hala güçlü bir dize dizisidir.
Nick VanderPyle

1
İşlenmeyen Özel Durum: System.IndexOutOfRangeException: Dizin, dizinin boun d'lerinin dışındaydı. at ArrayClass.Main (String [] args). İnt [] değişkenim = yeni int [] {}
yogesh

6
@yogesh: Bu garip. Örneğin kodu yazmak int[] variable = new int[]{}gibi bir döngüde yazmak ve kullanmak foreach (var s in variable){ Console.WriteLine(s);}için: int[] args1 = new int[0];ve foreach (int num in args1){Console.WriteLine(num);}. Yani kullanarak arasında hiçbir fark olmamalıdır new int[0]ve new int[]{}aynı koda derlenmiş hem get olarak.
Hayır

1
@GlennGordon Kesinlikle, ama bu C # sürüm 3.0'dan itibaren yeni (2007'den itibaren, Visual Studio 2008 ile). Bu sürüm var, yalnızca yerel değişkenler için de olsa (alanlar için değil) başka bir basit biçime izin verir . Ancak C # 2.0 (Visual Studio 2005) ve önceki sürümlerinde, bu yanıtın (veya string[] a = new string[0];) sözdizimini kullanmanız gerekiyordu .
Jeppe Stig Nielsen

113

.NET 4.6'da tercih edilen yol yeni bir yöntem kullanmaktır Array.Empty:

String[] a = Array.Empty<string>();

Uygulama kullanarak, özlü olduğu jenerik sınıflarında statik üyeleri .NET nasıl davrandığını :

public static T[] Empty<T>()
{
    return EmptyArray<T>.Value;
}

// Useful in number of places that return an empty byte array to avoid
// unnecessary memory allocation.
internal static class EmptyArray<T>
{
    public static readonly T[] Value = new T[0];
}

(açıklığa kavuşturmak için kod sözleşmesiyle ilgili kod kaldırıldı)

Ayrıca bakınız:


@Cole Johnson - Düzenleme için teşekkürler, ama geri aldım. Bu satırları bilerek atladım: Sadece ilginç uygulamayı alıntılamak istedim. Kod sözleşmesi ve nitelikler sadece neler olduğunu anlama yoluna girer (kaynak bağlantısı elbette her şeye sahiptir). Ayrıca, Yığın Taşması üzerinde kaydırma yapılmasını önlemek için yorumda yeni bir satır ekledim. Sakıncası yoksa, bu şekilde tercih ederim. Teşekkürler!
Kobi

2
Okunabilirlik için kesinlikle bir iyileştirme:Enumerable.Empty<T>().ToArray()
DanielV

Bu yöntem çoğu durumda kesinlikle tercih edilmesine rağmen, orijinal soruyu cevaplamamaktadır. OP boş bir dizi oluşturmak istiyor . Array.Empty<T>()yok değil bir dizi oluşturmak. Önceden ayrılmış bir diziye başvuru döndürür.
l33t

33

0 boyutuyla başlatabilirsiniz, ancak dizinin sonuna eklenemediğinden, boyutun ne olduğunu bildiğinizde yeniden başlatmanız gerekir.

string[] a = new string[0];

Bu doğru cevap
abzarak

7

Boyutsuz bir dizi bildirmenin fazla bir anlamı yoktur. Bir dizi yaklaşık boyuttadır . Belirli bir boyutta bir dizi bildirdiğinizde, bir koleksiyonda bulunan şeyleri tutabilecek sabit yuva sayısını belirtirsiniz ve buna göre bellek ayrılır. Bir şey eklemek için, zaten mevcut diziyi yeniden başlatmanız gerekir (diziyi yeniden boyutlandırsanız bile, bu iş parçacığına bakın ). Boş bir dizi başlatmak istediğiniz nadir durumlardan biri, diziyi bağımsız değişken olarak geçirmek olacaktır.

Hangi boyutta olabileceğini bilmediğinizde bir koleksiyon tanımlamak istiyorsanız, dizi seçiminiz değil, bir List<T>veya benzeri bir şeydir .

Bununla birlikte, boyutu belirtmeden bir diziyi bildirmenin tek yolu, boş bir 0 dizisine sahip olmaktır . hemant ve Alex Dn iki yol sunuyor. Başka bir basit alternatif sadece :

string[] a = { };

[ Köşeli ayraç içindeki öğelerin, örneğin, tanımlanan türe örtük olarak dönüştürülebilir olması gerekirstring[] a = { "a", "b" }; ]

Ya da bir başkası:

var a = Enumerable.Empty<string>().ToArray();

İşte daha açıklayıcı bir yol :

public static class Array<T>
{
    public static T[] Empty()
    {
        return Empty(0);
    }

    public static T[] Empty(int size)
    {
        return new T[size];
    }
}

Şimdi arayabilirsiniz:

var a = Array<string>.Empty();

//or

var a = Array<string>.Empty(5);

1
Bir dizi parametre olarak geçmek zorunda dışında herhangi bir kullanım düşünemiyorum. Bir yöntemin bir dizi nesneyi kabul ettiği ve varsayılan eylemi gerçekleştirmek için boş bir dizi geçirmek isteyebileceğiniz birkaç yansıması vardır. Cevabımı düzenleyeceğim.
nawfal

Örneğin, bir IEnumerable döndüren birkaç sınıf tarafından uygulanan bir arabiriminiz var ve uygulamalardan birinin yöntem için öğeleri yok ve örneğin boş bir dizi döndürüyor.
Ignacio Soler Garcia

@IgnacioSolerGarcia Bu durumda sadece son derece performans açısından kritik bir uygulama ise bir dizi döndürürdüm. Dizilerin modası geçmiş olduğunu söyleyebilirim ve eğer mümkünse kaçınılmalıdır. Lippert ve bu SO sorusu
nawfal

Döndürülen türün IEnumerable olduğunu unutmayın, böylece dizi salt okunurdur ve değiştirilmesi amaçlanmamıştır. Bu durumda neden bir Liste döndüreyim?
Ignacio Soler Garcia

1
Boş bir dizi için bir kullanım örneği basittir - nesneyi doldurmak istediğinizde ve kaç tane ekleyeceğinizi bilmiyorsanız!
vapcguy

6

Basit ve zarif!

string[] array = {}

Büyük harfle yazıldığında bir anahtar kelime olduğu gibi , arraysadece aolarak değiştiririm array. Bir anahtar kelime adını değişken adı olarak kullanmak kötü bir uygulamadır - durum farklı olsa bile. Ve temelde cevabımın aynısı String.Empty, orada olduğum dışında .
vapcguy

1
1. dizi ac # anahtar sözcüğü değildir. Dizi bir sınıf ve bir anahtar kelime 2 değil. "A" da kötü bir uygulamadır (belki de anahtar kelimeleri kullanmaktan daha kötü bir uygulamadır)
disklosr

Teknik olmak. Sınıf, anahtar kelime, bir nesne türünü tanımlar ve hala kötüdür. Neden akötü olduğunu düşünüyorsun ?
vapcguy

1
Çünkü tanımlayıcı olmayan ve tek harfli değişken isimleri kötü uygulamalardır çünkü onları tanımlamanın ardındaki nedeni aktarmazlar. "dizi" kesinlikle "a" dan daha iyi bir isimdir. Daha iyi bir isim "emptyArray" olur.
disklosr

4

string[] a = new string[0];

veya kısa gösterim:

string[] a = { };

Şimdi tercih edilen yol:

var a = Array.Empty<string>();

Sıfır uzunlukta ayırma örneğin değiştirmek istiyorsanız Visual Studio'da kullanabileceğiniz kısa bir düzenli ifade yazdım new string[0]. Düzenli İfade seçeneği açıkken Visual Studio'da Bul (arama) işlevini kullanın:

new[ ][a-zA-Z0-9]+\[0\]

Şimdi Tümünü Bul veya F3 (Sonrakini Bul) ve yerine Array.Empty <…> ()!


3

Dizi boyutunu çalışma zamanında tanımlayabilirsiniz .

Bu, dizinin boyutunu dinamik olarak hesaplamak için her şeyi yapmanızı sağlar. Ancak, bir kez tanımlandığında boyut değişmez.

Array a = Array.CreateInstance(typeof(string), 5);

4
Neden bütün bunlar? Çalışma zamanında dizi boyutunu normalde bir değişkenden tanımlayabilirsiniz:int i = 5; string[] a = new string[i];
Kevin Brock

Sanırım jeneriklerle bu modası geçmiş gibi görünüyor.
radarbob

2

Denedim:

string[] sample = new string[0];

Ama içine sadece bir dize ekleyebilirim ve sonra bir exceptionOutOfBound hatası aldım, bu yüzden sadece bunun için bir boyut koydum

string[] sample = new string[100];

Ya da benim için çalışan başka bir yol:

List<string> sample = new List<string>();

Liste için Değer Atama:

sample.Add(your input);

1

Bildiğim gibi boyut olmadan dizi yapamazsınız, ancak kullanabilirsiniz

List<string> l = new List<string>() 

ve sonra l.ToArray().


1

@Nawfal & @Kobi önerilerini birleştirmek:

namespace Extensions
{
    /// <summary> Useful in number of places that return an empty byte array to avoid unnecessary memory allocation. </summary>
    public static class Array<T>
    {
        public static readonly T[] Empty = new T[0];
    }
}

Kullanım örneği:

Array<string>.Empty

GÜNCELLEME 2019-05-14

(@Jaider ty'e aktarılır)

Daha iyi kullanım .Net API:

public static T[] Empty<T> ();

https://docs.microsoft.com/en-us/dotnet/api/system.array.empty?view=netframework-4.8

Şunun için geçerlidir:

.NET Core: 3.0 Önizleme 5 2.2 2.1 2.0 1.1 1.0

.NET Framework: 4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6

.NET Standardı: 2.1 Önizleme 2.0 1.6 1.5 1.4 1.3

...

HTH


1
.NET Core 2'de zaten bir uzantı var,arr = Array.Empty<string>();
Jaider

iirc, .NetStandart [4. bir şey] - de var.
ShloEmi

0

Yapabilirsin:

string[] a = { String.Empty };

Not: OP bir boyut belirtmek zorunda değil, bir diziyi boyutsuz yapmaz


8
Bu, uzunluk 1 dizesini oluşturmayacak mı?
Sumner Evans

Doğru, ama temizlendi. Ve OP bir boyutu belirtmek zorunda kalmadan diziyi bildirmek istedi - bu uyuyor.
vapcguy

Ve bu bir düşüşü hak ediyor, neden? OP specifybir boyuta sahip olmak değil, bir dizi yapmak anlamına geliyordu sizeless.
vapcguy

1
@vapcguy Ben downvoter'dım. Pişmanım. Cevabımı iptal etmek için cevabınızı düzenledim. Yorumunuz soruyu biraz şüpheli kılıyor. OP'nin ne anlama geldiğinden emin değilim.
nawfal

4
OP boş bir dizi istedi . Bu dizi boş değil.
Keith

0

İşte gerçek bir dünya örneği. Burada diziyi foundFilessıfır uzunluğa ilklendirmek gerekir .

(Diğer cevaplarda vurgulandığı gibi: Bu, bir öğe değil, özellikle dizin sıfırlı bir öğe değil, dizinin uzunluğu 1 olduğu anlamına gelir. Dizinin bu satırdan sonra sıfır uzunluğu vardır!).

Parça = string[0]atlanırsa, bir derleyici hatası vardır!

Bunun nedeni, geri çekilmeden catch bloğudur. C # derleyicisi Directory.GetFiles(), dizinin başlatılmaması için işlevin bir Özel Durum atabileceği kod yolunu tanır .

Kimsenin söylemeden önce, istisnayı yeniden değerlendirmemek hata işlemeyi kötü olurdu: Bu doğru değil. Hata işleme gereksinimleri karşılamalıdır.

Bu durumda, okunamayan ve kesilemeyen bir dizin durumunda programın devam etmesi gerektiği varsayılır - bunun en iyi örneği bir dizin yapısı üzerinden geçen bir işlevdir. Burada hata işleme sadece günlüğe kaydediyor. Tabii ki bu daha iyi yapılabilirdi, örneğin başarısız olan tüm dizinleri toplamakGetFiles(Dir) çağrıları olan , ancak bu çok ileri götürecektir.

Kaçınmanın throwgeçerli bir senaryo olduğunu belirtmek yeterlidir ve bu nedenle dizinin sıfır uzunluğuna başlatılması gerekir. Bunu catch bloğunda yapmak yeterli olacaktır, ancak bu kötü bir stil olacaktır.

GetFiles(Dir)Diziyi yeniden boyutlandırma çağrısı .

string[] foundFiles= new string[0];
string dir = @"c:\";
try
{
    foundFiles = Directory.GetFiles(dir);  // Remark; Array is resized from length zero
}
// Please add appropriate Exception handling yourself
catch (IOException)
{
  Console.WriteLine("Log: Warning! IOException while reading directory: " + dir);
  // throw; // This would throw Exception to caller and avoid compiler error
}

foreach (string filename in foundFiles)
    Console.WriteLine("Filename: " + filename);
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.