2011-01-12 70 views
1

我想我在这里有一个基本的误解。为什么测试失败?关闭和参考设置

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

它为什么会成为 “B”?你只是在各个点上通过值传递一个字符串引用。 – 2011-01-12 23:27:57

+0

我的想法是这样的:对“b”(newValue)的引用和对“a”(oldValue)的引用将提供给方法* To *,该方法将返回一个用于将newValue分配给OldValue的lambda。这个lambda将由行* Assign.TheValue(b).To(a.Name)(); *中的第三组圆括号进行评估。显然,我的理解是完全错误的。 – Ben 2011-01-12 23:56:09

回答

4

它失败了,因为参数To是按值传递的。

只因为oldValue设置为“b”并不意味着a.Name将根本改变。在调用To(a.Name)中,将表达式a.Name评估为字符串引用,并且该引用通过值传递给该方法。

这是基本的parameter passing in 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

换句话说,

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