Закрытия и настройки ссылок - PullRequest
1 голос
/ 13 января 2011

Я думаю, что у меня есть фундаментальное недоразумение здесь.Почему тест не пройден?

public static class ObjectExtensions
{
  public static Action To<T>(this T newValue, T oldValue) where T : class
  {
    return () => oldValue = newValue;            
  }
}

public static class Assign
{
  public static T TheValue<T>(T theValue)
  {
    return theValue;
  }
}

public class Tests 
{
  public void Test()
  {
    var a = new TestType { Name = "a" };
    var b = "b";
    Assign.TheValue(b).To(a.Name)();

    Assert.That(a.Name == "b"); //fails (a.Name == "a")
  }
}

public class TestType { public string Name {get;set;} }

Ответы [ 2 ]

4 голосов
/ 13 января 2011

Сбой, потому что аргументы To передаются по значению.

То, что для oldValue установлено значение "b", не означает, что a.Name изменится вообще. В вызове To(a.Name) выражение a.Name оценивается как строковая ссылка, и эта ссылка передается методу по значению.

Это базовая передача параметров в C # . Просто использование замыкания не меняет этого.

Что вы можете сделать, это изменить To метод следующим образом:

public static Action To<T>(this T newValue, Action<T> setter) where T : class
{
    return () => setter(newValue);
}

затем измените вызов на:

Assign.TheValue(b).To(x => a.Name = x)();
1 голос
/ 13 января 2011

Другими словами,

var a = new TestType { Name = "a" };
Assign.TheValue(b).To(a.Name)();

эквивалентно

Assign.TheValue(b).To("a")();

точно так же, как

int x = 5;
Convert.ToDecimal(x);

эквивалентно

Convert.ToDecimal(5);
...