2010-07-18 22 views
2

Pensez le code suivant:Comment passer un tableau d'octets en lecture seule?

static int Main() { 
    byte[] data = File.ReadAllBytes("anyfile"); 
    SomeMethod(data); 
    ... 
} 
static void SomeMethod(byte[] data) { 
    data[0] = anybytevalue; // this line should not be possible!!! 
    byte b = data[0];  // only reading should be allowed 
    ... 
} 

Est-il possible de passer l'octet readonly [] en C#? La copie n'est pas une solution. Je ne voudrais pas perdre de mémoire (parce que le fichier pourrait devenir très gros). S'il vous plaît garder la performance à l'esprit!

+0

C# est déjà dans vos tags. S'il vous plaît ne pas dupliquer cela dans votre titre. –

+0

Désolé, je ne savais pas! – raisyn

Répondre

11

Vous pouvez passer un ReadOnlyCollection<byte>, comme ceci:

static int Main() { 
    byte[] data = File.ReadAllBytes("anyfile"); 
    SomeMethod(new ReadOnlyCollection<byte>(data)); 
    ... 
} 
static void SomeMethod(ReadOnlyCollection<byte> data) { 
    byte b = data[0];  // only reading is allowed 
    ... 
} 

Cependant, il serait préférable de passer un Stream, comme ceci:
De cette façon, vous ne serez pas lire le fichier en mémoire à tout.

static int Main() { 
    Stream file = File.OpenRead("anyfile"); 
    SomeMethod(file); 
    ... 
} 
static void SomeMethod(Stream data) { 
    byte b = data.ReadByte();  // only reading is allowed 
    ... 
} 
+0

Y a-t-il des différences de performances lors de l'utilisation de ReadOnlyCollection au lieu de la baie? – raisyn

+0

@youllknow: Non mesurable; 'ReadOnlyCollection' est un wrapper fin autour d'un' IList '. – SLaks

+0

@youllknow: Comme SLaks mentionné, ReadOnlyCollection est en fait un wrapper autour IList . L'accès à un élément est donc un appel de méthode * et * un appel d'interface. C'est très cher, comparé au coût d'accès à un seul octet dans un tableau (comme 20x plus cher). Si votre tableau est grand, veillez à le profiler! – Niki

2

Je vous recommande d'utiliser l'objet le plus élevé possible dans la hiérarchie qui effectue le travail. Dans votre cas, ce serait IEnumerable<byte>:

static int Main() 
{ 
    byte[] data = File.ReadAllBytes("anyfile"); 
    SomeMethod(data); 
} 

static void SomeMethod(IEnumerable<byte> data) 
{ 
    byte b = data.ElementAt(0); 
    // Notice that the ElementAt extension method is sufficiently intelligent 
    // to use the indexer in this case instead of creating an enumerator 
} 
+0

'((octets []) données) [0] = anybytevalue;' – SLaks

+2

@Slaks, sûr casting, mais peu importe ce que vous essayez il y aura toujours des façons de contourner cela. Par exemple la réflexion. Donc, même avec une ReadOnlyCollection , l'utilisateur sera capable de modifier la structure originale des octets (bien qu'il devra écrire un peu plus de code que simplement lancer). J'ai supposé que le PO était à la recherche d'un temps de sécurité de compilation ici et non d'exécution. –

+0

Eh bien, vous * pourriez * créer une copie des données avec Enumerable.ToList. Pas moyen de contourner cela avec une distribution ou une réflexion. Je ne le recommanderais pas, cependant. – Niki

4

Je pense que cela pourrait être ce que vous cherchez.

compilez le code ci-dessous et vous obtiendrez cette erreur de compilation: propriété ou indexeur « Stack2.MyReadOnlyBytes.this [int] » ne peut pas être attribué à - il est en lecture seule

public class MyReadOnlyBytes 
{ 
    private byte[] myData; 

    public MyReadOnlyBytes(byte[] data) 
    { 
     myData = data; 
    } 

    public byte this[int i] 
    { 
     get 
     { 
     return myData[i]; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var b = File.ReadAllBytes(@"C:\Windows\explorer.exe"); 
     var myb = new MyReadOnlyBytes(b); 

     Test(myb); 

     Console.ReadLine(); 
    } 

    private static void Test(MyReadOnlyBytes myb) 
    { 
     Console.WriteLine(myb[0]); 
     myb[0] = myb[1]; 
     Console.WriteLine(myb[0]); 
    } 
} 
+0

belle solution aussi! avez-vous fait des comparaisons de vitesse? – raisyn

+0

n'ont pas fait de comps de vitesse –

+0

La meilleure solution à mon avis. Merci. – Darkonekt