चेतावनी के लिए कारण भाग में समझाया जाता है The issue with T?
की बाहर Nullable संदर्भ प्रकार की कोशिश करें । लंबी कहानी छोटी, यदि आप उपयोग करते T?
हैं तो आपको यह निर्दिष्ट करना होगा कि प्रकार एक वर्ग या संरचना है। आप प्रत्येक मामले के लिए दो प्रकार का निर्माण कर सकते हैं।
गहरी समस्या यह है कि परिणाम को लागू करने के लिए एक प्रकार का उपयोग करना और सफलता और त्रुटि दोनों मानों को पकड़ना एक ही समस्या को वापस लाता है परिणाम को ठीक करना चाहिए था, और कुछ और।
- उसी प्रकार के आसपास एक मृत मान रखना है, या तो प्रकार या त्रुटि, या वापस नल लाने के लिए
- प्रकार पर पैटर्न का मिलान संभव नहीं है। यह काम करने के लिए आपको कुछ फैंसी पोजिशनल पैटर्न मिलान अभिव्यक्ति का उपयोग करना होगा।
- नल से बचने के लिए आपको F # के विकल्पों के समान विकल्प / हो सकता है, का उपयोग करना होगा । आप अभी भी मूल्य और त्रुटि के लिए या तो आसपास कोई भी नहीं ले जाएगा।
परिणाम # (या तो) F # में
प्रारंभिक बिंदु F # का परिणाम प्रकार और भेदभाव रहित संघ होना चाहिए । सब के बाद, यह पहले से ही .NET पर काम करता है।
F # में एक परिणाम प्रकार है:
type Result<'T,'TError> =
| Ok of ResultValue:'T
| Error of ErrorValue:'TError
प्रकार स्वयं ही वे ले जाते हैं जिनकी उन्हें आवश्यकता होती है।
F # में DU बिना किसी आवश्यकता के नल के बिना संपूर्ण पैटर्न की अनुमति देते हैं:
match res2 with
| Ok req -> printfn "My request was valid! Name: %s Email %s" req.Name req.Email
| Error e -> printfn "Error: %s" e
सी # 8 में यह अनुकरण
दुर्भाग्य से, C # 8 के पास अभी तक DU नहीं हैं, वे C # 9 के लिए निर्धारित हैं। C # 8 में हम इसका अनुकरण कर सकते हैं, लेकिन हम थकावट से मेल खाते हैं:
#nullable enable
public interface IResult<TResult,TError>{}
struct Success<TResult,TError> : IResult<TResult,TError>
{
public TResult Value {get;}
public Success(TResult value)=>Value=value;
public void Deconstruct(out TResult value)=>value=Value;
}
struct Error<TResult,TError> : IResult<TResult,TError>
{
public TError ErrorValue {get;}
public Error(TError error)=>ErrorValue=error;
public void Deconstruct(out TError error)=>error=ErrorValue;
}
और इसका उपयोग करें:
IResult<double,string> Sqrt(IResult<double,string> input)
{
return input switch {
Error<double,string> e => e,
Success<double,string> (var v) when v<0 => new Error<double,string>("Negative"),
Success<double,string> (var v) => new Success<double,string>(Math.Sqrt(v)),
_ => throw new ArgumentException()
};
}
एग्जॉस्ट पैटर्न के मिलान के बिना, हमें कंपाइलर चेतावनियों से बचने के लिए उस डिफ़ॉल्ट क्लॉज को जोड़ना होगा।
मैं अभी भी मृत मूल्यों को पेश किए बिना संपूर्ण मिलान प्राप्त करने का एक तरीका ढूंढ रहा हूं , भले ही वे सिर्फ एक विकल्प हों।
विकल्प / संभवत:
जिस तरह से संपूर्ण मिलान का उपयोग करता है, उससे एक वैकल्पिक वर्ग बनाना सरल है:
readonly struct Option<T>
{
public readonly T Value {get;}
public readonly bool IsSome {get;}
public readonly bool IsNone =>!IsSome;
public Option(T value)=>(Value,IsSome)=(value,true);
public void Deconstruct(out T value,out bool isSome)=>(value,isSome)=(Value,IsSome);
}
//Convenience methods, similar to F#'s Option module
static class Option
{
public static Option<T> Some<T>(T value)=>new Option<T>(value);
public static Option<T> None<T>()=>default;
}
जिसका उपयोग इसके साथ किया जा सकता है:
string cateGory = someValue switch { Option<Category> (_ ,false) =>"No Category",
Option<Category> (var v,true) => v.Name
};