2017-10-03 3 views
0

Est-il possible de le faireinstanciation une classe à l'intérieur d'une méthode

void Instantiate(Class c) { 
    c = new Class(); 
} 

Class c1 = null; 
Instantiate(c1); 
c1.property .....gives me null reference exception 

une classe peut être instanciée dans une méthode et être utilisé en dehors d'elle?

+0

Vous devez passer 'c1' par référence. – MarcinJuraszek

+0

@MarcinJuraszek, merci pour la réponse mate, mais les types de référence ne reçoivent pas leur référence lorsque vous les passez à une méthode? oh cela arrive-t-il seulement si c'est instancié avant d'être passé à la méthode? –

+0

J'ai mis à jour ma réponse avec une explication. Longue histoire courte - en C# tous les paramètres sont passés par valeur par défaut. Pour le type de référence, la valeur est la référence (adresse) de l'objet. Mais cette référence est copiée, donc si vous la modifiez à l'intérieur de la méthode, elle ne reflète pas en dehors de la méthode. Vous devez le passer par 'ref' pour y arriver. – MarcinJuraszek

Répondre

0

Oui, mais vous devez passer l'argument par référence:

void Instantiate(ref Class c) { 
    c = new Class(); 
} 

Class c1 = null; 
Instantiate(ref c1); 

Tous les paramètres sont passés par valeur par défaut. Dans le cas des types de référence, la référence est la valeur transmise. A cause de cela, si vous changez l'état interne de l'objet, il sera visible en dehors de la méthode (par exemple en ajoutant un élément à une liste). Mais, mais vous ne pouvez pas remplacer l'instance entière - cette modification ne sera pas visible pour l'appelant.

Disons que vous avez un List<T>:

var myList = new List<T>(); 

supposons qu'il est initialisé dans un emplacement de mémoire 0x1234. Maintenant, vous passez à une méthode qui prend List<T>:

void doSomethingWithAList(List<T> list) 
{ 
} 

Et plus tard

doSomethingWithAList(myList); 

A ce stade, les deux myList en dehors de la méthode et list l'intérieur doSomethingWithAList point les mêmes addres (0x1234). Si vous faites list.Add(default(T)) et plus tard appelez myList.Lenghth vous obtiendrez 1, car ils pointent tous deux sur le même objet à 0x1234.

Cependant, si à l'intérieur doSomethingWithAList vous attribuez une nouvelle liste à list:

void doSomethingWithAList(List<T> list) 
{ 
    list = new List<T>(); 
} 

seulement list points ce nouvel objet. myList points encore à 0x1234.

Une fois que vous faites la méthode prendre List<T> par référence mise à jour de ce point list aussi également mettre à jour ce que myList des points à l'extérieur de la méthode.

+0

Comprendre, Merci encore une fois mate! –

0

Je pense que la confusion est que tous les paramètres sont passés par valeur à une autre méthode. Ainsi, lorsque vous passez un type de référence dans une méthode, une copie de la référence est transmise à la méthode.

Dans votre exemple, c1 pointe initialement sur null. Lorsque vous appelez instantiate, une copie de c1, je vais le nommer c1_ est créé (ce qui indique null) et c1_ est passé dans la méthode Instantiate, pas c1.

Il y a deux façons de faire fonctionner votre code. La première est l'utilisation du mot-clé ref. Le mot clé ref permettra à c1 d'être transmis dans la méthode.

void Instantiate(ref Class c) { 
    c = new Class(); 
} 

et l'appeler en tant que tels

Instantiate(ref c1); 

Je vous recommande d'utiliser un type de retour dans cet exemple spécifique.

Class Instantiate() { 
    return new Class(); 
} 

Vous pouvez utiliser la méthode de la manière suivante.

Class c1 = Instantiate(); 
+0

Merci pour l'explication @Paul, faire plus de sens! –