2013-01-14 8 views
5

Mi piacerebbe passare un sottoinsieme di un array C# in un metodo. Non mi interessa se il metodo sovrascrive i dati, quindi vorrei evitare di creare una copia.Fogli di array C# senza copia

C'è un modo per farlo?

Grazie.

risposta

10

Modificare il metodo per prendere uno IEnumerable<T> o ArraySegment<T>.

È quindi possibile passare new ArraySegment<T>(array, 5, 2)

+0

È possibile aggiungere un esempio di "IEnumerable " con "Salta"/"Take". –

+1

@StefanSteinegger: 'ArraySegment ' implementa 'IEnumerable ' – SLaks

+0

Brillante, grazie. – user1400716

1

Gli array sono immutabili per dimensione (ovvero non è possibile modificare le dimensioni di un array), quindi è possibile solo passare una copia sottratta dell'array originale. Come opzione è possibile passare due indici da un array originale al metodo e operare sulla base di due ulteriori indici.

-2

è possibile utilizzare LINQ prendere funktion e prendere il maggior numero di elementi dell'array come si desidera

var yournewarray = youroldarray.Take(4).ToArray(); 
+3

Se si aggiunge 'ToArray' alla fine, si sta eseguendo una copia. Dovresti anche usare sia "Skip" e "Take" per ottenere un sottoinsieme arbitrario. Infine, se vuole un accesso rapido indicizzato all'interno del sottoinsieme, non lo otterrà da un 'IEnumerable'. – Servy

+0

-1: OP ha pubblicato appositamente che non _non_ vuole una copia. – Tom

2

È possibile utilizzare la seguente classe. Nota che potrebbe essere necessario modificarlo a seconda se si desidera che endIndex sia inclusivo o esclusivo. Puoi anche modificarlo per iniziare e contare, piuttosto che un inizio e un indice finale.

Non ho intenzionalmente aggiunto metodi mutabili. Se specificatamente lo vuoi, è abbastanza facile aggiungerlo. Potresti anche voler implementare IList se aggiungi i metodi mutabili.

public class Subset<T> : IReadOnlyList<T> 
{ 
    private IList<T> source; 
    private int startIndex; 
    private int endIndex; 
    public Subset(IList<T> source, int startIndex, int endIndex) 
    { 
     this.source = source; 
     this.startIndex = startIndex; 
     this.endIndex = endIndex; 
    } 

    public T this[int i] 
    { 
     get 
     { 
      if (startIndex + i >= endIndex) 
       throw new IndexOutOfRangeException(); 
      return source[startIndex + i]; 
     } 
    } 

    public int Count 
    { 
     get { return endIndex - startIndex; } 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return source.Skip(startIndex) 
      .Take(endIndex - startIndex) 
      .GetEnumerator(); 
    } 

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