2010-04-29 73 views
10

是否可以很容易地動態裝飾和?例如,可以說我有一個List<PointF>。這個列表實際上是正弦函數的情節。我想通過這些要點併爲每個PointF添加一個標誌,判斷它是否爲高峯。動態裝飾c中的物體#

但我不想創建一個新的擴展的SpecialPointF或其他任何具有布爾屬性的東西。

判斷我所有你想要的懶惰,但懶惰的思想是如何真棒出生(也壞主意)

編輯:我會接受拳擊解決方案,以及任何有趣的黑客,你可以拿出。沒有什麼能夠阻止我獲得。我只想知道是否有更有趣的方式。

+1

我剛剛給你+1的結束句。但是,不太確定你的問題的答案。 – 2010-04-29 16:56:34

回答

4

如果有一種方法可以計算每點的數據,則不需要向其添加標誌,您可以使用extension方法,而無需對其進行擴展。

Something like PointF.isPeak();

它的工作原理是這樣的:

public static class Extensions 
{ 
    public static bool isPeak (this PointF p) 
    { 
     do crazy math... 

     return result; 
    } 
} 

,瞧,你有你的PointF類的計算。

順便說一句,公共靜態類必須在最外層的範圍內,不能嵌套。

+1

+1。非常好的建議,儘管'isPeak'沒有與.NET命名約定一致(第一個字符應該大寫) – 2010-04-29 17:11:53

+0

這是一個很棒的想法。我喜歡它。 – 2010-04-29 17:17:12

+0

@Francisco:擴展方法是一個好主意,但是在這種情況下,一個點將如何知道它不在其中的高峯?除非點包含指向該系列的指針,否則它是... – 2010-04-29 17:18:39

5

不,沒有辦法做(具體)你要求什麼。

假設您使用的是C#3.0+,您可以使用匿名類型來執行此操作,前提是您不希望在函數之外公開信息。

var decoratedList = sourceList.Select(pt => new 
        { 
         IsPeak = GetIsPeak(pt), 
         Point = pt 
        }).ToList(); 

這會給你一個新的List<T>對象。這可能不能解決您的問題,因爲您無法將此功能擴展到單個功能調用之外,並且您正在創建一個新列表,而不是修改現有列表,但希望這會有所幫助。

+0

這是一個很酷的想法。我還沒有使用匿名類型,所以我甚至沒有考慮過。 我們使用最新的c#非常酷,所以它不是問題。 – 2010-04-29 17:07:46

+0

@Oren:他們很好,但最大的缺陷是無法將他們暴露在你的功能之外。如果你需要這樣做,你必須創建一個類似簽名的自己的簡單包裝類,然後只說'新的WrapperClass {...'而不是'new {...' – 2010-04-29 17:09:35

2

不,這是不可能的。

最近將剛剛創建

var decorationData = new Dictionary <Object, bool> 

,然後在那裏保存的值。不需要直接擴展類型。您甚至可以使用擴展方法來訪問存儲的數據,然後該數據看起來像是對象的直接屬性。

public static class PointFPeakExtensions 
{ 
    private static var decorationData = new Dictionary <PointF, bool> 

    public static bool IsPeak (this PointF point) 
    { 
     return decorationData[point]; 
    } 
    public static void SetPeak (this PointF point, bool isPeak) 
    { 
     decorationData[point] = isPeak; 
    } 
} 

並添加到您的編輯:

你也可以使用包含剛裝修的數據和引用類型(同樣爲可空類型在類庫實現了一個通用型解決這個)。然而,這仍然意味着你必須改變你使用類型的地方的簽名(這可能不是你在尋找裝飾器時想做的事情)。

3

可能有可能做到這一點使用新的dynamic關鍵字和ExpandoObject建立在C#4.0,但我沒有與它的第一手經驗呢。據我瞭解,是爲了輕鬆解決這個確切的問題,因此可以說

dynamic something = new ExpandoObject(); 
something.Anything = "whatever you want"; 

相信有可能擴展動態現有的類型,但它可能需要創建一個新的子類,它會破壞練習的全部目的。

可以使用擴展方法創建幾乎相同的解決方案。 ExpandoObject在內部實現爲Dictionary,但它添加了優雅的本地語法。

class Program { 

    static void Main(string[] args) 
    { 
     PointF p = new PointF(0, 0); 

     p.SetFlag(true); 

     if (p.GetFlag()) 
     Console.WriteLine("win"); 
    } 

} 

public static class Extensions 
{ 
    private static Dictionary<PointF, bool> flags = new Dictionary<PointF, bool>(); 
    public static bool GetFlag(this PointF key) 
    { 
     return flags[key]; 
     //OR return flags.ContainsKey(key) ? flags[key] : false; 
    } 

    public static void SetFlag(this PointF key, bool val) 
    { 
     flags[key] = val; 
    } 
} 
+0

而不是p.SetFlag你的意思是調用Extensions.SetFlag(p,true); ? – 2010-04-29 17:18:27

+0

不,擴展方法允許你打電話看起來像這樣「原生」。它會自動爲您調用'Extensions.SetFlag(p,true)'。 – 2010-04-29 17:21:17