Soru 'Enum' dizisini 'int' dizisine dönüştürme


Bir Enum dizisini bir int dizisine dönüştürmeye çalışıyorum:

public enum TestEnum
{
Item1,
Item2
}

int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(Convert.ToInt32));

Bazı nedenlerle Convert.ToInt32, Array.ConvertAll içinde kullanıldığında çalışmaz, bu yüzden bazı değişiklikler yapmak zorunda kaldım:

int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(ConvertTestEnumToInt));

public static int ConvertTestEnumToInt(TestEnum te)
{
return (int)te;
}

Sadece meraktan, bu ekstra bir yöntem kullanmadan çalışmak için herhangi bir yolu var mı?

Saygılarımızla


28
2018-01-23 09:43


Menşei


Örneğiniz int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(Convert.ToInt32)); gerçekten aynı int[] result = Array.ConvertAll(enumArray, Convert.ToInt32);. Aşırı yük ToInt32 Söz konusu yöntem bir object parametre. Temsilci türü (yapılandırılmış genel bir tür Converter<TestEnum, int>) bir alır TestEnum. Şimdi beri TestEnum türetmek object, her şeyin işe yaramadığına şaşırdın. Fakat bu tür bir sihir (C # 2'de geldi) sadece izin verilir referans tipleri, ve TestEnum bir değer türü. - Jeppe Stig Nielsen
Şimdi, Gravell'in cevabı en iyi çözümü verirken, yaklaşımınız yazarak onarabilir. int[] result = Array.ConvertAll(enumArray, x => Convert.ToInt32(x));. Bu durumda lambda, görünmez bir boks TestEnum için object. Ama dediğim gibi, Gravell'in çözümü daha zarif ve hızlı. - Jeppe Stig Nielsen


Cevaplar:


Sadece anonim bir yöntem kullanarak yayınlayın:

int[] result = Array.ConvertAll<TestEnum, int>(
    enumArray, delegate(TestEnum value) {return (int) value;});

veya C # 3.0 ile bir lambda:

int[] result = Array.ConvertAll(enumArray, value => (int) value);

39
2018-01-23 09:47



+1 int [] result = Array.ConvertAll (enumArray, value => (int) value) ile bana itin; - johnc
Çok hoş! Sadece kodda kullanılan ve bir cazibeye benzeyen, uzun listeyi tek tek dönüştürmek için hiç olmadığı kadar güzel. Teşekkürler! - rball
Kadar basit bir şey hakkında nasıl int[] res = (int[])(object)enumArray;? Cevabımı gör. Tabii ki, boks dahil, ama lanet, çok şaşırdım. :) - quetzalcoatl
@quetzalcoatl aslında herhangi bir boks içermez; garip - Oldukça işe yaramadığından eminim, ancak eski çerçevelerde başarısızlığa uğratamam. - Marc Gravell♦
Çok Güzel Cevap! Yardımın için teşekkürler: D - Jake Steele


Neyse ki bizim için C # 3.0 bir Cast operasyon:

int[] result = enumArray.Cast<int>().ToArray();

Dizileri kullanmayı bırakıp kullanmaya başlarsanız IEnumerable<>hatta ToArray() aramak.


38
2018-02-13 17:43



Bu kabul edilen cevap olmalı. - EriF89
Cevabınız hiç mantıklı değil. ne enumArray ? - BaltoStar


TestEnumArray.Select (x => (int) x)) ToArray ()


4
2017-10-09 13:51





FYI: .Net4ClientProfile ve VS2010 üzerinde test edildi

Aslında, LINQ kullanmanıza bile gerek yok. Türü aşağıya bırakmanız şartıyla, normal bir şekilde yayınlayabilirsiniz. object.

Having:

  enum One { one0, one1, one2, one3 };
  enum Two { two0, two1, two2, two3 };

  One[] vals = new One[] { One.one0, One.one3 };

oynayabiliriz:

//Two[] aa = (Two[])vals; // impossible
  Two[] aa = (Two[])(object)vals; // possible!

  Two bb = aa[1]; // == Two.two3

İlk başta, ikinci hattın InvalidCast'i atmadığı konusunda gerçekten şaşırdım. Ama öyle değil.

Türlere bakmak bazı şeyleri biraz açıklıyor:

  bool check2 = bb.GetType().FullName == "Two";   // well, you'd guess that
  bool check3 = aa.GetType().FullName == "One[]"; // what?!

Ciddi anlamda! aa dizi değil Two[]. Dizine eklendiğinde dizi türü "değişken tarafından kaybedildi" object, ama ikisi de vals ve (object)vals Tabii ki hala aynı nesneye başvurur. Sonra, aşağıdaki oyunculardan sonra, hala aa nesne, orijinal dizi One[]Sadece yeni bir değişken tipinin arkasına gizlenmiş.

bb nesne / değişken türü Two dizinin öğesinin bir öğe olarak okunması nedeniyle Two[] dizi (değişkenin türleri ile birlikte). Gerçek dizi One [] tarafından gizlenir Two[] tip, böylece indeksleme Two[] değerinin olması gerekir Two yazın.

Ayrıca, gerçek tür gizlendiğinden ve Enum türlerinin hafifçe ele alındığından beri, başka bir şeyi kontrol edelim:

  var numbers = (int[])(object)vals;
  var cc = numbers[0] + 10; // == 10, from one0's value
  var dd = numbers[1] + 10; // == 13, from one3's value

ve benzer şekilde:

  bool check4 = numbers.GetType().FullName == "One[]"; // not System.Int32[]

Yani, tahmin edebileceğiniz gibi, başka bir yol da mümkündür:

  var numbers2 = new int[]{ 0, 2, 99 };
  var enums = (One[])(object)numbers2;
  One ee = enums[0]; // == One.one0
  One ff = enums[1]; // == One.one2
  One gg = enums[2]; // == ((One)99)

ve int [] ayrıca gerçek türünü de hatırlar. One[]:

  bool check5 = numbers2.GetType().FullName == "System.Int32[]";

Daha da ileride, as ve is dizi geçtiğinde operatörler object:

  bool really_true1 = vals is One[];
  bool really_true2 = vals is Two[];
  bool really_true3 = vals is System.LoaderOptimization[];

Bu bir 'gotha' idi! son zamanlarda benim için.

Aslında Yeniden kullanılmamış orijinal dizi nesnesini (LINQ ile kopyalamak yerine) ve bunu farklı tür olarak gösterir - İki [] veya int []. Bir "gerçek oyuncu", boks yok gibi görünüyor. LINQ-yönlendirmeli kopyalama ve dönüştürme çok farklı.


1
2018-01-17 12:32



btw: her zamanki gibi, JS zaten bunun hakkında yazdı (stackoverflow.com/a/15168879/717732) ve onun sözleri, CLR'nin hiçbir fark olmadığını bildiğinden fazladan boks olmadığını ileri sürüyor. - quetzalcoatl
Bu boks değil; Bir dizi her zaman bir referans türü olduğundan, bir diziyi "kutulayamazsınız"; çok ilginç - Marc Gravell♦
Not için teşekkürler, neden bu terimlerle düşünmediğimi bilmiyorum ve buna açıkça bakın. Metindeki bitleri düzelttim. - quetzalcoatl
@MarcGravell: Hiç boks olmadığından emin misin? Belki de bu terimlerdeki diziler biraz özeldir? Birkaç şeyi kontrol ettim, örneğin: var x = (object[])(object)(new List<int>[5]) geçerli bir yayın, ancak (object[])(object)(new int[5]) geçerli bir yayın değil ve (object[])(object)(new One[5]) aynı zamanda geçerli değil (object[])(object)(new System.Enum[5]) geçerli. Belki bir şeyi tekrar unutmuşum, ama bütün dizi ya 'değer dizisi' ya da 'ref dizisi' gibi görünüyor. Not arasındaki fark bu int/One ve Enumikincisi, 'ref / object', eski-değer olarak kabul edilir. - quetzalcoatl
@MarcGravell haklı, boks değil. Örnekte (int[])(object)(new One[5]) Çalışma zamanının türleri dikkate alması gerçeğini "yanlış kullanıyoruz" int[] ve One[] Bir anlamda, birbirinden atanabilir. C #, bu durumda çalışma zamanının atama kavramına katılmıyor. Örnekte (object[])(object)(new System.Enum[5]) sadece kullanıyoruz dizi kovaryansı sadece sınıfları ile çalışır (yani referans tipleri). Bunu hatırla System.Enum bir classreferans tipi, the base class of your Biri. - Jeppe Stig Nielsen


int [] b = Array.ConvertAll ((int []) Enum.GetValues ​​(typeof (testEnum)), Convert.ToInt32);


1
2017-11-11 22:55





Bu bir çekicilik gibi çalıştı:

var intArray = enumArray.Select(e => (int)e).ToArray();

bu gibi:

var intList = enumArray.Select(e => (int)e).ToList();

1
2018-05-08 15:58