generics - वीएस 2012 और वीएस 2015 के बीच एफ#के द्वारा अस्पष्ट सामान्य इंटरफेस के उपचार के बीच का अंतर बाद में त्रुटियों को संकलन करने के लिए अग्रणी



visual-studio-2012 interface (1)

(नोट: प्रश्न पूर्ण प्रतिलिपि प्रस्तुत करने योग्य उदाहरण के साथ अपडेट किया गया)

वीएस 2012 से वी.एस. 2015 तक एफ # प्रोजेक्ट को स्थानांतरित करने के बाद मुझे इंटरफेस के कुछ उपयोगों पर त्रुटि मिलती है। विशेष रूप से ऐसा होता है जहां एक प्रकार दो सामान्य इंटरफेस लागू होता है। मुझे पता है कि एफ # में सीधे अनुमति नहीं है, लेकिन यह प्रकार सी # से आता है।

समस्या को पुन: उत्पन्न करने के लिए:

1. सी # में परिभाषा प्रकार:

इसे कुछ कक्षा पुस्तकालय में पेस्ट करें

public interface Base { }

public interface IPrime<T> : Base
{
    T Value { get; }
}


public interface IFloat : IPrime<double>
{
}

public interface IInt : IFloat, IPrime<int>
{
    int Salary { get; }
}

public abstract class Prime<T> : IPrime<T>
{
    public T Value { get; protected internal set; }

    public static implicit operator T(Prime<T> value)
    {
        return value.Value;
    }
}


public class FFloat : Prime<double>, IFloat
{
    public FFloat(double value)
    {
        this.Value = value;
    }
    public double Salary { get; set; }
}

public class FInt : Prime<int>, IInt
{
    public FInt(int value)
    {
        this.Value = value;
    }
    public int Salary { get; set; }
    int IPrime<int>.Value { get { return this.Value; } }
    double IPrime<double>.Value { get { return this.Value; } }
}

2. एफ में प्रकारों का उपयोग:

दृश्य स्टूडियो 2012 में उपयोग, काम कर रहा है:

open SomeClassLib

[<EntryPoint>]
let main argv = 
    let i = new FInt(10)
    let f = new FFloat(12.0)
    let g = fun (itm: SomeClassLib.Base) -> 
        match itm with
        | :? IInt as i -> i.Value
        | :? IFloat as i -> i.Value |> int
        | _ -> failwith "error"

यदि आप विज़ुअल स्टूडियो 2015 में एक ही समाधान खोलते हैं तो आपको त्रुटि मिलती है

त्रुटि FS0001: प्रकार बेमेल लिखें। float -> float अपेक्षा float -> float लेकिन एक float -> int दिया float -> int'float' प्रकार 'int' मेल नहीं खाता

यह निश्चित रूप से एक टाइपकास्ट द्वारा आसानी से ठीक किया जाता है, लेकिन फिर, आश्चर्य की बात है, यह अब दृश्य स्टूडियो 2012 में लोड नहीं होगा (अच्छी तरह से, इसे दोनों में काम करने के तरीके हैं, और इस उदाहरण में यह तुच्छ है)।

3. निष्कर्ष

यदि आप i.Value पर होवर करते हैं i.Value आप प्राप्त करते हैं:

विजुअल स्टूडियो 2012

| :? IInt as i -> i.Value          // Value is int
| :? IFloat as i -> i.Value |> int // Value is float

विजुअल स्टूडियो 2015

| :? IInt as i -> i.Value          // Value is float
| :? IFloat as i -> i.Value |> int // Value is float

मैं सोच रहा हूँ कि यह अंतर कहां से आता है।

प्रश्न / टिप्पणी

मुझे यह अजीब लगता है कि कंपाइलर को "चुनना" लगता है कि एक असाइनमेंट काम करता है, और दूसरा, यह अनजाने और कभी-कभी मुश्किल गलतियों के लिए आमंत्रित करता है और स्पष्ट रूप से, मैं थोड़ा चिंतित हूं कि स्थानों में प्रकार का अनुमान इंट और फ्लोट के बीच चुन सकता है, यह अब फ्लोट के पक्ष में होगा, जहां यह अतीत में अंतर था।

2012 और 2015 के बीच का अंतर ऐसा लगता है कि पिछला वर्ग के ऊपर होने के दौरान सबसे पहले मुठभेड़ों में सबसे पहले का समय लगता है, और बाद में आखिरी बार लगता है, लेकिन मैं इस बात की पुष्टि नहीं कर पा रहा हूं कि यह स्पष्ट नहीं है।

क्या यह एक बग या मौजूदा सुविधा का सुधार है? मुझे डर है कि मुझे अस्पष्टता को दूर करने के लिए कुछ नया करना होगा, जब तक कि कोई इस से निपटने का एक आसान तरीका जानता न हो (यह केवल 50 या तो स्थानों में होता है, हाथ से तय करने के लिए संभव है, लेकिन बहुत अच्छा नहीं) ?

प्रारंभिक निष्कर्ष

यह मुझे स्पष्ट है कि मूल प्रकार को अस्पष्ट और संभवत: खराब डिज़ाइन माना जा सकता है, लेकिन .NET भाषाओं का समर्थन करता है और ऐसा भी होता है MSIL

मुझे पता है कि एफ # समान पद्धति या संपत्ति पर सामान्य प्रकार के मिश्रणों का समर्थन नहीं करता है, जो कि एक भाषा विकल्प है जिसके साथ मैं रह सकता हूं, लेकिन इसका प्रकार अनुमान एक निर्णय करता है जिसे भविष्यवाणी नहीं किया जा सकता, जो मुझे लगता है कि एक बग है

किसी भी तरह से, मेरा मानना ​​है कि यह एक त्रुटि होनी चाहिए, जैसा कि आपको F # में सदस्यों द्वारा ओवरलोड किए जाने पर मिलता है, उस स्थिति में, जिस स्थिति में त्रुटि बहुत स्पष्ट है और विकल्प सूचीबद्ध करती है।


मैंने सी # कोड में इंटरफेस के आदेश को स्वैप किया और वीएस 2013 के रूप में संकलित निम्न कोड

public interface IInt : IPrime<int>, IFloat
{
   int Salary { get; }
}
let g = fun (itm: Base) -> 
    match itm with
    | :? IInt as i -> i.Value
    | :? IFloat as i -> i.Value |> int
    | _ -> failwith "error"

मुझे संदेह है कि इंटरफेस के आदेश के आधार पर 'वैल्यू' सदस्यों में से एक दूसरे द्वारा छिपा हुआ है (एफएसएचआरपी के नजरिए से छिपी हुई है)।

इसके बजाय मैंने आपके पैटर्न को इस तरह मिलान किया है, और पुष्टि की है कि इस मामले में इंटरफेस आदेश का कोई असर नहीं था।

let g = fun (itm: Base) -> 
    match itm with
    | :? IPrime<int> as i -> i.Value
    | :? IPrime<float> as i -> i.Value |> int
    | _ -> failwith "error"

मेरे लिए, यह कार्यान्वयन के विवरण में बदलाव की तरह लगता है। मुझे यकीन नहीं है कि मैं इसे बग कहूंगा। यदि यह एक बग है तो F # विनिर्देश अंतिम शब्द होगा।





visual-studio-2015