2016-07-12 7 views
1
type AdderType() = 
    /// Appends to the container. 
    static member (+) 
     (cont:DockPanel,child:#UIElement) = 
     cont.Children.Add child |> ignore 
     child 

Wenn ich die Klasse wie oben gemacht und versuchen Sie so etwas.Wie kann ich Operatoren für WPF-Container überladen?

let dock = DockPanel() 
let win = Window(Title = "Check the Window Style", Content = dock) 
let menu = dock + Menu() 

erhalte ich die Fehler None of the types 'DockPanel,Menu' support the operator '+'. ich inspiriert wurde, die oben durch Phil Trelford's Bindung Beispiel zu machen, die so geht:

type DependencyPropertyValuePair(dp:DependencyProperty,value:obj) = 
    member this.Property = dp 
    member this.Value = value 
    static member (+) 
     (target:#UIElement,pair:DependencyPropertyValuePair) = 
     target.SetValue(pair.Property,pair.Value) 
     target 

Die oben aus irgendeinem Grund funktioniert. Ich habe keine Idee warum. Wäre es möglich, den + oder einen anderen Operator zu überlasten, so dass ich Container elegant hinzufügen könnte?

+0

Sie können immer eine globale Überladung des Operators tun - aber Sie wollen nicht + in diesem Fall –

+0

Ich habe versucht, überladen '++' und '| +', aber es hat nicht funktioniert. –

+0

Und '% +%' gerade jetzt. Ich bezweifle, dass '-' funktionieren würde. Gibt es einen Trick? –

Antwort

7

Operatoren innerhalb einer Klasse definiert nur funktionieren, wenn eines der Argumente eine Instanz der Klasse ist, aber Sie können Ihre Betreiber als globaler Operator definieren:

let (++) (cont:DockPanel) (child:#UIElement) = 
    cont.Children.Add child |> ignore 
    child 

Folgendes sollte dann funktionieren:

let dock = DockPanel() 
let win = Window(Title = "Check the Window Style", Content = dock) 
let menu = dock ++ Menu() 

Aber um ehrlich zu sein, glaube ich nicht, dass diese Art von Problem ein guter Ort für die Verwendung von benutzerdefinierten Operatoren ist. Mit + hier ist verwirrend, weil Sie nicht wirklich zwei Dinge in irgendeinem Sinne hinzufügen. Ihr Operator ist nicht kommutativ, z.B. (a ++ b) <> (b ++ a).

denke ich, eine idiomatische Code wäre eine benannte Funktion zu definieren und verwenden, um den |>:

let appendTo (cont:DockPanel) (child:#UIElement) = 
    cont.Children.Add child |> ignore 
    child 

let dock = DockPanel() 
let win = Window(Title = "Check the Window Style", Content = dock) 
let menu = Menu() |> appendTo dock 
+0

Ich würde '(Forts: DockPanel)' in '(Forts: Panel)' ändern, da der Supertyp auch die 'Children' Eigenschaft hat. Ansonsten bin ich damit zufrieden. –

+1

+1: Die Verwendung von + hier ist verwirrend, weil Sie nicht wirklich zwei Dinge hinzufügen. Ihr Operator ist nicht kommutativ, z.B. (a ++ b) <> (b ++ a). –

+0

Ich glaube nicht, dass es ein Problem ist, dass der Bediener nicht kommutativ ist. String-Verkettung ist nicht kommutativ ('' "Hallo" + "Welt" <> "Welt" + "Hallo") und verwendet + Operator. Aber ich denke, dass das nicht assoziativ ist, z.B. (a + b) + c <> a + (b + c), ist verwirrend. – hvester

2

so, wie es wie im letzten Beispiel, wie dies wäre in ähnlicher Weise zu tun:

type ContainerType(con:Panel) = 
    member this.Children = con.Children 
    static member (+) 
     (child:#UIElement,cont:ContainerType) = 
     cont.Children.Add child |> ignore 
     child 

let toCon = ContainerType 

Eigentlich mag ich Tomas Lösung besser. Und Phil Trelford Beispiel sieht so sehr wie es ist ein Teil von .NET, dass es mir in den Sinn, dass eines der Argumente in der static member (+) hat DependencyPropertyValuePair als der Typ, warum der + Operator könnte in erster Linie überlastet werden. Also das beantwortet das.

Verwandte Themen