2010-09-20 4 views
2

Je viens d'essayer de coder la méthode d'extension suivante:Les méthodes d'extension peuvent-elles modifier les valeurs de classe étendues?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace _4Testing 
{ 
    static class ExtensionMethods 
    { 
     public static void AssignMe(this int me, int value) 
     { 
      me = value; 
     } 
    } 
} 

Mais il ne fonctionne pas, je veux dire, puis-je utiliser une méthode d'extension pour modifier les valeurs des classes étendues? Je ne veux pas changer le type de retour void en int, en changeant juste la valeur de classe étendue. Merci d'avance

Répondre

5

Votre exemple utilise int, qui est un type de valeur. Les classes sont des types de référence et se comportent un peu différemment dans ce cas.

Alors que vous pourriez faire une méthode qui prend une autre référence comme AssignMe(this MyClass me, MyClass other), la méthode fonctionnerait sur une copie de la référence, donc si vous attribuez other-me il ne toucherait que la copie locale de la référence. De plus, gardez à l'esprit que les méthodes d'extension ne sont que des méthodes statiques déguisées. C'est à dire. ils ne peuvent accéder qu'aux membres publics des types étendus.

public sealed class Foo { 
    public int PublicValue; 
    private int PrivateValue; 
} 

public static class FooExtensions { 
    public static void Bar(this Foo f) { 
     f.PublicValue = 42; 

     // Doesn't compile as the extension method doesn't have access to Foo's internals 
     f.PrivateValue = 42; 
    } 
} 
+0

Cool Brian! Laissez-moi maintenant revenir à mon IDE pour continuer à changer mon code. –

0

Ramon ce que vous avez vraiment besoin est un modificateur de ref sur le premier paramètre (à savoir me int) de la méthode d'extension, mais C# ne permet pas de modification ref sur les paramètres ayant « ce » modificateurs.

[Mise à jour] Aucune solution de contournement ne devrait être possible pour votre cas particulier d'une méthode d'extension pour un type de valeur. Voici la "reductio ad absurdum" que vous demandez si vous êtes autorisé à faire ce que vous voulez faire; Considérez l'énoncé de C#:
5.AssignMe(10);
... maintenant que pensez-vous que c'est supposé faire? Essayez-vous d'attribuer 10 à 5 ?? La surcharge de l'opérateur ne peut pas vous aider non plus.

+1

Donc, ma question était à la recherche d'une solution de contournement, en avez-vous une? Merci quand même –

1
// a work around for extension to a wrapping reference type is following .... 

using System; 


static class Program 
{ 

    static void Main(string[] args) 
    { 


    var me = new Integer { value = 5 }; 
    int y = 2; 

    me.AssignMe(y); 

    Console.WriteLine(me); // prints 2 

    Console.ReadLine(); 
    } 

    public static void AssignMe(this Integer me, int value) 
    { 

     me.value = value; 
    } 


} 

    class Integer 
    { 


     public int value { get; set; } 

     public Integer() 
    { 
     value = 0; 
    } 

    public override string ToString() 
    { 
     return value.ToString(); 
    } 

    } 
+0

Bon mumtaz! J'ai mis en place une solution similaire à la fin. –

0

Ceci est un ancien article mais j'ai rencontré un problème similaire en essayant d'implémenter un extendeur pour la classe String.

Mon code original était le suivant:

public static void Revert(this string s) 
{ 
    char[] xc = s.ToCharArray(); 
    s = new string(xc.Reverse()); 
} 

En utilisant le nouveau mot-clé Je suis en train de créer un nouvel objet et que s n'est pas passée par référence, il ne sera pas modifié.

je l'ai changé à la suivante qui fournit une solution au problème de Ramon:

public static string Reverse(this string s) 
{ 
    char[] xc = s.ToCharArray(); 
    Array.Reverse(xc); 
    return new string(xc); 
} 

Dans ce cas, le code d'appel sera:

s = s.Reverse(); 

Pour manipuler des nombres entiers que vous pouvez faire quelque chose comme:

public static int Increment(this int i) 
{ 
    return i++; 
} 

i = i.Increment();