2017-02-01 39 views
10

Bana öyle geliyor ki, F # seçenek türünün bazı özellikleri C# projelerinden görünmez. Türleri inceleyerek, az çok sebebi görebiliyorum, ama tam olarak neyin olup bittiğini, neden bu seçimlerin yapıldığını veya sorunu en iyi nasıl atlatacağımı anlamıyorum.Neden FSharpOption için bazı özellikler (ör. IsSome ve IsNone) C# 'den görünmüyor?

Sorunu gösteren bazı parçacıklar aşağıdadır. İki proje, bir C# projesi ve bir F # projesi içeren bir VS2015 çözümüm var.

type Foo() = 

    member this.Bar() = Some(1) 

Dahası, F # böyle bir şey yazabilirsiniz:

let option = (new Foo()).Bar() 
let result = if option.IsNone then "Is none" else "Is some" 

yüzden opsiyon tipi adında bir özelliğe sahip olduğunu görünür F # projede, ben olarak tanımlanan bir sınıf aşağıda var IsNone. Şimdi, C# projesinde, F # projesinden derlenen .dll dosyasına bir başvurum var. Bu, ör.

var optionType = new Foo().Bar(); 

değişken optionType bir FSharpOption<int> olup. Yukarıda işaret ettiğim gibi, F # projelerinde seçenek türlerini kullandığımda, genellikle IsSome ve IsNone özelliklerine erişebiliyorum. Ancak, optionType.IsNone gibi bir şey yazmaya çalıştığımda, "Özellik, dizinleyici veya olay ... dili tarafından desteklenmiyor" CS1546 hatası alıyorum.

FSharpOption class signature from C#: FSharpOption türünü teftiş Şimdi ne zaman

Intellisense does not detect the IsSome and IsNone properties

, ben IsNone ve IsSome "özellikleri" gibi statik yöntemler göründüğünü görebilirsiniz: Bununla uyumlu olarak, IntelliSense özelliği algılamaz

FSharpOption class signature from F#

01: Ben F # dan türünü incelemek diğer taraftan

, ben yerine aşağıdaki bakın

Burada, IsSome ve IsNone özelliklerinin "varlığı" belirgindir. İmleci bu özelliklerin üzerine getirerek, VS2015 bana şu notayı veriyor: "İçerdiği tür, nullar birliği durumu için bir '' null '' değerini gösterebilir. Bu üye bir statik üye olarak derlenecek.” Bu, özelliklerin statik yöntemler (lukegv ve Fyodor Soikin tarafından belirtildiği gibi) dışında mevcut olmamasının nedeni budur.

Yani, durum aşağıdaki gibi görünüyor: Derlenmiş FSharpOption türünde IsNone ve IsSome özellikleri yok. Bu özellikleri taklit eden işlevselliği etkinleştirmek için F # içindeki sahnelerin arkasında bir şeyler oluyor.

Bunu Microsoft.FSharp.Core içinde OptionModule kullanarak alabilirsiniz. Ancak, bu işlevsellik, F # çekirdek kütüphanesinin mimarları tarafından bilinçli bir seçim olduğu görülmektedir. Seçim nedenleri nelerdir? Ve OptionModule doğru çözüm kullanıyor ya da C# FSharpOption<T> türünü kullanmak için daha iyi bir yolu var mı?

cevap

10

Bu, option'un nasıl derlendiği ile ilgilidir. Some değerleri, sınıfın bir örneğini oluşturup değerin içine sarılmasıyla doğrudan doğruya derlenir. Ancak None değerleri gerçekten değerler değil, sadece null.

bu deneyin:

let a: int option = Some 1 
let b: int option = None 
let a_isNull = obj.ReferenceEquals(a, null) // a_isNull = false 
let b_isNull = obj.ReferenceEquals(b, null) // b_isNull = true 

Bu çalışma zamanında döngüleri çok kaydeder bir optimizasyon (bu da None değerleri will show up as null in the debugger's Watch window nedenidir). (ve CompilationRepresentationFlags.UseNullAsTrueValue uygulayarak kendi sendika türleriniz için de kullanabilirsiniz.

Şimdi, bu tür bazı değerler null olabileceğinden, bu değerlerdeki özellikleri veya yöntemleri gerçekten kullanamazsınız. Değer null olarak gerçekleşirse, yalnızca kilitlenirsiniz. Bu nedenle, tüm işlemler için her zaman OptionModule'u kullanmalısınız.

Bu özelliklerin neden intellisense'de görünmediğine gelince, bunlar static. Yine de neden orada olduklarından emin değilim. Belki bir derleyici artefakt.

+3

Teşekkürler, Hiçbiri değerlerinin gerçekten boş olması gerçeği, IsNone ve IsSome özelliklerinin neden kaldırıldığının iyi bir açıklamasıdır. Sorunuzu, sizin ve lukegv'in derlenmiş sınıfta "özellikler" in statik olduğunu belirtmek için biraz düzenledim. –

+0

Sooo ... Hala mekaniği ve nedenleri almıyor musunuz? Başka bir şey belirsiz mi? –

+0

Hayır, mantıklı, teşekkürler :-) –

2

ben de F # ile usta değilim, ama tüm CLR olduğundan, cevabım görünümünde bir C# noktadan geçerli: oluşturulan sınıf tanımının içinde

, hem IsNone ve IsSome statiktir ve bunun olamaz optionType numaralı örnek üzerinden erişilebilir (ne IntelliSense aracılığıyla, ne de kod). Value mülkü statik değildir ve erişilebilir.

İlgili konular