2011-01-12 104 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);