2009-03-08 7 views
4

J'utilise beaucoup l'héritage, le polymorphisme et l'encapsulation, mais je viens de réaliser que je ne connaissais pas le comportement suivant concernant la portée d'un objet par rapport à une variable. La différence est mieux représenté avec le code:C# Portée des variables vs objets lors du paramétrage dans les méthodes

public class Obj 
{ 
    public string sss {get; set;} 

    public Obj() 
    { 
     sss = "0"; 
    } 
}  

public partial class testScope : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     Obj a = new Obj(); 
     String sss = "0";    
     Context.Response.Write(sss); // 0 

     FlipString(sss); 
     FlipString(a.sss); 
     Context.Response.Write(sss + a.sss); // 0 0 

     FlipObject(a); 
     Context.Response.Write(a.sss); // 1 
     Context.Response.End(); 
    } 

    public void FlipString(string str) 
    { str = "1"; } 

    public void FlipObject(Obj str) 
    { str.sss = "1"; } 
} 

Je pensais que quand une variable est passée dans une méthode que les changements sont limités à la portée de la méthode. Mais il semble que si un objet est passé dans une méthode qui change à ses propriétés s'étendent au-delà de la méthode.

Je pourrais accepter ceci si la règle était que ce comportement existe pour l'objet et pas les variables mais dans. Net tout est un objet, une chaîne (comme celle dans l'exemple est System.String) Donc quelle est la règle, comment puis-je prédire la portée d'un paramètre que je passe dans une méthode?

Répondre

18

Vous passez jamais un objet comme argument - vous ne passez jamais une référence ou une valeur de type de valeur. Sauf si vous utilisez le mot clé ref, les arguments sont passés par valeur, c'est-à-dire que la valeur initiale du paramètre est la valeur évaluée de l'argument et que les modifications apportées à la valeur du paramètre ne sont pas visibles par l'appelant.

Cependant, il est très important de comprendre que la valeur du paramètre (pour un type de référence) est juste la référence. Si vous changez le contenu de l'objet auquel la référence fait référence, alors que changera sera vu par l'appelant.

C'est un sujet qui mérite plus que quelques paragraphes - je vous suggère de lire mon article about parameter passing in .NET pour plus d'informations.

+0

merci jon, je vais être sûr d'accepter la réponse plus tard dans la journée plutôt que tôt pour max rep :) – rizzle

+0

LOL: Je ne m'inquiéterais pas à ce sujet - ce n'est pas un gros problème. Une meilleure réponse peut très bien venir. –

+0

+1 sur la mention d'un sujet qui devient trop peu de discussion. – jro

1

Je pense que je viens de comprendre googleing autour, certaines choses dans .net sont des types "valeur" et d'autres sont des types "référence", donc pour les types de valeur, la valeur est dupliquée lors du marshaling dans une méthode, Les types ont un pointeur similaire, ou une référence passée dans la méthode qui partage évidemment la même portée que le parent. Alors, ma question est de savoir comment savoir si quelque chose est un type de valeur ou non, je vois que les structures comme les int sont tous des types de valeur mais les chaînes semblent se comporter comme des structures même si elles sont des objets System.String?

+1

Les chaînes sont toujours des types de référence, mais elles sont immuables. Ils ne se comportent pas réellement comme des struc- tures - ils se comportent comme des types de référence. La seule chose qui les fait ressembler un peu à des structs est qu'ils sont immuables, mais vous pouvez aussi écrire vos propres types de références immuables. –

+0

Le point clé consiste à différencier entre la modification de la valeur d'un paramètre pour faire référence à un objet différent et la modification du contenu d'un objet * référencé par * par le paramètre. –

1

Une classe (Obj dans votre cas) est un reference type, donc lorsque vous appelez la fonction, ce que vous faites est de passer une référence (vous pouvez essentiellement considérer cela comme un pointeur de type sécurisé) à cet objet. Si vous souhaitez empêcher les modifications d'objets mutables (c'est-à-dire les types classe/référence), vous devez cloner cet objet avant de le passer à la fonction appropriée (ou simplement en faire une structure pour qu'elle soit copiée par valeur).

Questions connexes