Mam tablicę X zawierającą 10 elementów. Chciałbym utworzyć nową tablicę zawierającą wszystkie elementy z X, które zaczynają się od indeksu 3, a kończą na indeksie 7. Jasne, że mogę łatwo napisać pętlę, która to zrobi za mnie, ale chciałbym zachować mój kod tak czysty, jak to możliwe . Czy istnieje metoda w C #, która może to dla mnie zrobić?
Coś w stylu (pseudo kod):
Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)
Array.Copy
nie pasuje do moich potrzeb . Potrzebuję elementów z nowej tablicy, aby były klonami. Array.copy
to tylko memcpy
odpowiednik w stylu C. Nie szukam tego.
Odpowiedzi:
Możesz dodać go jako metodę rozszerzenia:
Zaktualizuj klonowanie (co nie było oczywiste w pierwotnym pytaniu). Jeśli naprawdę chcesz głębokiego klona; coś jak:
Wymaga to jednak możliwości serializacji (
[Serializable]
lubISerializable
) obiektów. Można łatwo zastąpić każdy inny serializatora jako właściwy -XmlSerializer
,DataContractSerializer
, protobuf netto itpZauważ, że głęboki klon jest trudny bez serializacji; w szczególności
ICloneable
trudno jest zaufać w większości przypadków.źródło
Możesz użyć
Array.Copy(...)
do skopiowania do nowej tablicy po jej utworzeniu, ale nie sądzę, że istnieje metoda, która tworzy nową tablicę i kopiuje zakres elementów.Jeśli używasz .NET 3.5 Państwo mogli używać LINQ:
ale będzie to nieco mniej wydajne.
Zobacz odpowiedź na podobne pytanie, aby uzyskać informacje na temat bardziej szczegółowych sytuacji.
źródło
Czy zastanawiałeś się nad użyciem
ArraySegment
?http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx
źródło
IEnumerable<T>
i wiele innych przydatnych interfejsów.ArraySegment
odpowiedzi na pierwotne pytanie?IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
Widzę, że chcesz wykonać Klonowanie, a nie tylko kopiowanie referencji. W takim przypadku możesz użyć
.Select
do rzutowania członków tablicy na ich klony. Na przykład, jeśli Twoje elementy zostały zaimplementowane,IClonable
możesz zrobić coś takiego:Uwaga: To rozwiązanie wymaga .NET Framework 3.5.
źródło
IEnumerable
. Mogę dostaćIEnumerable
,IList
,IArray
itp ... z minimalnym zamieszanie, inline, jeśli muszę. Jeśli nie potrzebuję głębokiej kopii, po prostu usuwamSelect
. UpuszczenieSkip
lubTake
pozwala mi kontrolować zasięg. Alternatywnie, mogę to pomieszać zSkipWhile
i / lubTakeWhile
.Poniższy kod robi to w jednym wierszu:
źródło
W C # 8 wprowadzili nowy
Range
iIndex
typźródło
źródło
Opierając się na odpowiedzi Marca, ale dodając pożądane zachowanie klonowania
A jeśli implementacja ICloneable jest zbyt ciężka, to refleksyjna przy użyciu biblioteki Håvarda Strandena do kopiowania, aby wykonać wymagane ciężkie podnoszenie.
Należy pamiętać, że implementacja OX.Copyable działa z dowolnym z:
Powinno to obejmować prawie każdą sytuację. Jeśli klonujesz obiekty, w których wykres podrzędny zawiera takie elementy, jak połączenia db lub uchwyty plików / strumieni, oczywiście masz problemy, ale jest to prawdą w przypadku każdej uogólnionej głębokiej kopii.
Jeśli zamiast tego chcesz zastosować inne podejście do głębokiego kopiowania, w tym artykule wymieniono kilka innych, więc sugeruję, aby nie próbować pisać własnego.
źródło
Możesz to zrobić dość łatwo;
źródło
Myślę, że kod, którego szukasz to:
Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)
źródło
Alternatywnie do kopiowania danych możesz utworzyć opakowanie, które daje dostęp do części oryginalnej tablicy, tak jakby była kopią części tablicy. Zaletą jest to, że nie dostajesz kolejnej kopii danych w pamięci, a wadą jest niewielki narzut podczas uzyskiwania dostępu do danych.
Stosowanie:
źródło
Array.ConstrainedCopy będzie działać.
źródło
Nie ma jednej metody, która spełni Twoje oczekiwania. Musisz udostępnić metodę klonowania dla klasy w tablicy. Następnie, jeśli LINQ jest opcją:
źródło
Co powiesz na użycie Array.ConstrainedCopy :
Poniżej znajduje się mój oryginalny post. To nie zadziała
Możesz użyć Array.CopyTo :
źródło
Co powiesz na to:
Następnie musisz zaimplementować interfejs ICloneable we wszystkich klasach, na których musisz go używać, ale to powinno wystarczyć.
źródło
Nie jestem pewien, jak głęboko jest naprawdę, ale:
MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()
Jest to trochę narzut, ale może wyeliminować niepotrzebną metodę.
źródło
C # 8 zapewnia funkcję o nazwie Range, aby uzyskać subarry od początku do końca indeksu. możesz użyć tego w ten sposób.
źródło
Jeśli chodzi o klonowanie, nie sądzę, że serializacja wywołuje twoich konstruktorów. Może to zepsuć niezmienniki klasy, jeśli robisz ciekawe rzeczy w ctor's.
Wydaje się, że bezpieczniejszym rozwiązaniem są wirtualne metody klonowania wywołujące konstruktory kopii.
źródło
Klonowanie elementów w tablicy nie jest czymś, co można zrobić w uniwersalny sposób. Czy chcesz głębokiego klonowania czy zwykłej kopii wszystkich członków?
Przejdźmy do podejścia „najlepszego wysiłku”: klonowania obiektów za pomocą interfejsu ICloneable lub serializacji binarnej:
To nie jest idealne rozwiązanie, ponieważ po prostu nie ma takiego, który działałby dla dowolnego typu obiektu.
źródło
Możesz wziąć udział w zajęciach wykonanych przez Microsoft:
i wtedy
źródło
Przekonałem się, że jest to optymalny sposób:
Mam nadzieję, że to pomoże!
źródło
użyj metody rozszerzenia:
i możesz z niego korzystać
źródło
Kod z System.Private.CoreLib.dll:
źródło
Nie spełnia twoich wymagań dotyczących klonowania, ale wydaje się łatwiejsze niż wiele odpowiedzi do zrobienia:
źródło
źródło