Могут ли методы расширения изменять значения расширенного класса? - PullRequest
2 голосов
/ 20 сентября 2010

Я просто пытался закодировать следующий метод расширения:

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;
        }
    }
}

Но это не работает, я имею в виду, могу ли я использовать метод расширения для изменения значений из расширенных классов?Я не хочу менять тип возвращаемого значения void на int, просто меняю значение расширенного класса.Заранее спасибо

Ответы [ 4 ]

5 голосов
/ 20 сентября 2010

В вашем примере используется int, который является типом значения. Классы являются ссылочными типами и в этом случае ведут себя немного иначе.

Хотя вы можете создать метод, который использует другую ссылку, такую ​​как AssignMe(this MyClass me, MyClass other), метод будет работать с копией ссылки, поэтому, если вы присвоите other me, это повлияет только на локальную копию ссылки ,

Кроме того, имейте в виду, что методы расширения являются просто скрытыми статическими методами. То есть они могут получить доступ только к публичным членам расширенных типов.

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; 
   }
}
1 голос
/ 21 сентября 2010
// 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 голосов
/ 14 января 2013

Это старый пост, но я столкнулся с подобной проблемой, пытаясь реализовать расширитель для класса String.

Мой оригинальный код был таким:

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

Используя новое ключевое слово, я создаю новый объект и, поскольку s не передается по ссылке, он не будет изменен.

Я изменил его на следующее, что обеспечивает решение проблемы Рамона:

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

В этом случае код вызова будет:

s = s.Reverse();

Для манипулирования целыми числами вы можете сделать что-то вроде:

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

i = i.Increment();
0 голосов
/ 20 сентября 2010

Рамон, что вам действительно нужно, это модификатор ref для первого (то есть int me) параметра метода расширения, но C # не позволяет модификатор ref для параметров, имеющих модификаторы 'this'.

[Обновление] В вашем конкретном случае метода расширения для типа значения обходного пути быть не должно.Вот «reductio ad absurdum», о котором вы спрашиваете, разрешено ли вам делать то, что вы хотите;рассмотрим утверждение C #:
5.AssignMe(10);
... теперь, что, по-вашему, вы предполагаете сделать?Вы пытаетесь назначить от 10 до 5 ??Перегрузка оператора вам тоже не поможет.

...