2015-03-18 1 views
1

J'ai cet exemple de code. Ce que je veux faire est de faire en sorte que la valeur "Nums" ne puisse être écrite qu'en utilisant la méthode "AddNum".Faire une liste en lecture seule dans C#

namespace ConsoleApplication1 
{ 
    public class Person 
    { 
     string myName = "N/A"; 
     int myAge = 0; 
     List<int> _nums = new List<int>(); 

     public List<int> Nums 
     { 
      get 
      { 
       return _nums; 
      } 
     } 

     public void AddNum(int NumToAdd) 
     { 

      _nums.Add(NumToAdd); 
     } 

     public string Name { get; set; } 
     public int Age { get; set; } 
    } 
} 

D'une certaine façon, j'ai essayé un tas de choses en ce qui concerne AsReadOnly() et le mot-clé en lecture seule, mais je ne peux pas sembler obtenir à faire ce que je veux faire.

Voici l'exemple du code que j'ai pour accéder à la propriété.

Person p1 = new Person(); 
p1.Nums.Add(25); //access 1 
p1.AddNum(37); //access 2 

Console.WriteLine("press any key"); 
Console.ReadLine(); 

Je veux vraiment « accès 1 » à l'échec, et « l'accès 2 » à être le seulement manière que la valeur peut être réglée. Merci d'avance pour l'aide.

+1

vous l'avez pointé dans votre propre tag: utilisez ['ReadOnlyCollection'] (https://msdn.microsoft.com/fr-fr/library/ms132474 (v = vs.110) .aspx) pour votre propriété ou faites juste une copie de votre liste dedans (de cette façon un utilisateur peut changer sa copie mais pas votre état interne) – Carsten

+0

Essayez de faire Nums une fonction qui retourne un tableau, pas une liste. – LarsTech

+0

utiliser "Liste privée Nums" au lieu de public Liste Numéros –

Répondre

3

√ NE PAS utiliser ReadOnlyCollection, une sous-classe de ReadOnlyCollection, ou dans de rares cas IEnumerable biens immobiliers ou de retour des valeurs représentant collections en lecture seule.

La citation de this article.

Vous devriez avoir quelque chose comme ceci:

List<int> _nums = new List<int>(); 

public ReadOnlyCollection<int> Nums 
{ 
    get 
    { 
     return _nums.AsReadOnly(); 
    } 
} 
2

En général, les types de collections permettent de propriétés pauvres parce que même quand une collection est enveloppé dans ReadOnlyCollection, il est en soi pas claire:

IEnumerable<int> nums = myPerson.Nums; 
myPerson.AddNum(23); 
foreach(int i in nums) // Should the 23 be included!? 
    ... 

est censé vouloir dire. L'objet renvoyé par Nums est-il un instantané des numéros qui existaient lors de l'appel, s'agit-il d'une vue en direct?

Une approche plus propre consiste à avoir une méthode appelée quelque chose comme GetNumsAsArray qui renvoie un nouveau tableau chaque fois qu'il est appelé; il peut également être utile dans certains cas d'avoir une variante GetNumsAsList en fonction de ce que l'appelant voudra faire avec les nombres. Certaines méthodes ne fonctionnent qu'avec des tableaux, et d'autres ne fonctionnent qu'avec des listes. Si l'un des éléments ci-dessus est fourni, certains appelants devront l'appeler, puis convertir l'objet renvoyé en le type requis.

Si les appelants de performance sensibles auront besoin d'utiliser ce code beaucoup, il peut être utile d'avoir une méthode d'usage général plus:

int CopyNumsIntoArray(int sourceIndex, int reqCount, ref int[] dest, 
         int destIndex, CopyCountMode mode); 

où CopyCountMode indique ce que le code devrait faire le nombre de les articles disponibles à partir de sourceIndex est supérieur ou inférieur à reqCount; la méthode doit renvoyer le nombre d'éléments disponibles ou lancer une exception si elle ne respecte pas les attentes exprimées par l'appelant. Certains appelants peuvent commencer par créer et transmettre un tableau de 10 éléments, mais être prêts à remplacer la méthode par un plus grand tableau s'il y a plus de dix éléments à retourner; d'autres peuvent s'attendre à ce qu'il y ait exactement 23 éléments et ne soient pas préparés à gérer un autre nombre. L'utilisation d'un paramètre pour spécifier le mode permettra à une méthode de traiter plusieurs types d'appelants. Bien que de nombreux auteurs de collection ne s'embarrassent pas d'inclure une méthode qui correspond au modèle ci-dessus, ces méthodes peuvent grandement améliorer l'efficacité dans les cas où le code veut travailler avec une minorité significative d'une collection (par exemple, 1 000 éléments d'une collection de 50 000).En l'absence de telles méthodes, le code souhaitant travailler avec une telle gamme doit soit demander une copie de l'ensemble (très gaspillage) soit demander des milliers d'articles individuellement (gaspillage également). Permettre à l'appelant de fournir le tableau de destination améliorerait l'efficacité dans le cas où la même méthode fait beaucoup de requêtes, en particulier si le tableau de destination est suffisamment grand pour être placé sur le tas d'objets volumineux.

+0

Hey supercat, -je suivre environ 40% de ce que vous dites .. quand je lance le code que vous avez donné dans mon exemple: IEnumerable Nums = myPerson.Nums; myPerson.AddNum (23); foreach (int i en nums) // Faut-il inclure le 23 !? ... le 23 est inclus voulez-vous dire que ce ne devrait pas être? .. ou est-ce une question pour moi? – stumped221

+0

@ stumped221: Certaines personnes regardant juste le code appelant (mais incapable de voir l'implémentation de 'Nums') s'attendraient à ce que le 23 soit inclus; certains s'attendraient à ce que cela ne soit pas inclus. Une bonne API devrait - dans la mesure du possible - être écrite de sorte que les personnes qui ne regardent que le code d'appel puissent raisonnablement deviner ce que cela signifie, mais il n'y a aucun moyen qu'une propriété 'Nums' puisse se comporter sans surprise une fraction significative de personnes regardant le code côté client. En revanche, si le code appelle 'GetNumsAsArray', quiconque voit l'appel de la méthode s'attend à ce qu'il obtienne un instantané. – supercat

+0

Hmmm .. pouvez-vous me donner un exemple d'un scénario où quelqu'un instancie un objet, attribue explicitement ou insère une valeur à une propriété de cet objet, puis ne s'attend pas à ce que la valeur qu'ils viennent d'ajouter apparaisse dans leur instance objet? Je suis un peu nouveau dans le monde OOP, alors je ne fais que poser des questions sur le plan éducatif. – stumped221