2012-01-19 16 views
12

से कई परिणामों को लौटाने का प्रयास करें, मैं कोशिश करें कैच ब्लॉक और बेहतर त्रुटि प्रबंधन का उपयोग करके अपने कौशल में सुधार करने की कोशिश कर रहा हूं।विधि

मेरे पास एक ऐसा वर्ग है जो एक सामान्य कार्य करता है, इस मामले में एक फेसबुक एक्सेस टोकन पुनर्प्राप्त करता है। यदि सफल हो, तो मैं AccessToken स्ट्रिंग को वापस करना चाहता हूं, अगर नहीं, तो मैं एक त्रुटि संदेश वापस करना चाहता हूं। ये दोनों तार हैं, इसलिए कोई समस्या नहीं है। लेकिन कोड के कॉलिंग पक्ष पर रिटर्न वैल्यू की जांच करते समय, आप इसे प्रभावी ढंग से कैसे कर सकते हैं?

ऐसा लगता है कि मुझे 2 मान वापस करने की आवश्यकता है। सफल प्रयास के मामले में, वापसी = सत्य, "ACESSCODEACXDJGKEIDJ", या यदि यह विफल हो जाता है, तो वापसी = झूठी, "ओउप्स, एक त्रुटि हुई" + ex.ToString();

फिर वापसी मूल्य की जांच करना आसान है (सिद्धांत में)। मैं वापसी के लिए बस एक सच्चा/झूठा लौटने और स्ट्रिंग के लिए सत्र चर सेट करने के बारे में सोच सकता था।

किसी विधि से कई परिणाम लौटने का तरीका क्या है?

उत्तर

21

एक परिणाम वर्ग बना सकते हैं और है कि बजाय वापसी मिलता है ...

public class Result 
{ 
    public bool Success {get;set;} 
    public string AccessToken {get;set;} 
    public string ErrorMessage {get;set;} 
} 


public Result GetFacebookToken() 
{ 
    Result result = new Result(); 

    try{ 
     result.AccessToken = "FACEBOOK TOKEN"; 
     result.Success = true; 
    } 
    catch(Exception ex){ 
     result.ErrorMessage = ex.Message; 
     result.Success = false; 
    } 

    return result; 
} 

तो फिर तुम इस कोड की तरह कॉल कर सकते हैं ...

Result result = GetFacebookToken(); 

if(result.Success) 
{ 
    //do something with result.AccessToken 
} 
else 
{ 
    //do something with result.ErrorMessage 
} 
+0

मई के साथ-साथ इसे किसी भी परिणाम प्रकार पर जेनेरिक बना सकते हैं, ju नहीं सेंट 'एक्सेस टोकन' – Alexander

1

मैं त्रुटि संदेश नहीं लौटाऊंगा। एक सार्थक मूल्य लौटाएं या त्रुटि दें और इसे बबल करें। आप त्रुटि को कैसे संभालेंगे, लेकिन कम से कम मैं इसे फ्रंट एंड पर गहराई से संभालता हूं और बैकएंड पर किसी को लॉग/सूचित करता हूं।

आप कुछ भी लौटने जब अपने कार्य त्रुटियों बाहर तो मैं एक वस्तु निम्नलिखित सदस्य हैं कि वापसी होगी पर जोर देते हैं:

Value - String 
Success - Bool 

तो फिर तुम सफलता के लिए जाँच करें और तदनुसार मूल्य संभाल कर सकते हैं।

3

ऐसा करने का एक शानदार तरीका एक ऐसी वस्तु को वापस कर रहा है जिसमें सफलता/विफलता स्थिति और विस्तृत त्रुटि संदेश दोनों शामिल हों।

कुछ की तरह:

class Result 
{ 
    bool IsSuccessful { get; set; } 
    string DetailedStatus { get; set; } 
} 
8

2 संभावनाओं वसंत मन में

  1. उपयोग TryXXX पैटर्न (जैसे DateTime.TryParse के रूप में कुछ बीसीएल तरीकों में प्रयुक्त)।
  2. ऑपरेशन की स्थिति और परिणाम रखने वाली कक्षा को डिज़ाइन करें और फिर अपनी विधि इस कक्षा को वापस कर दें।

आइए पहले tryXXX पैटर्न देखें। यह मूल रूप से एक विधि है जो एक बूलियन मान देता है और परिणाम out पैरामीटर के रूप में देता है।

public bool TryXXX(string someInput, out string someResult, out string errorMessage) 
{ 
    ... 
} 

जो इस तरह भस्म हो जाएगा:

string someResult; 
string errorMessage; 
if (!TryXXX("some parameter", out someResult, out errorMessage)) 
{ 
    // an error occurred => use errorMessage to get more details 
} 
else 
{ 
    // everything went fine => use the results here 
} 

दूसरा दृष्टिकोण आप बस एक वर्ग है कि सभी आवश्यक जानकारी होगी डिजाइन करेंगे में:

public class MyResult 
{ 
    public bool Success { get; set; } 
    public string ErrorMessage { get; set; } 

    public string SomeResult { get; set; } 
} 

और उसके बाद अपने विधि इस वर्ग को वापस करें:

public MyResult MyMethod(string someParameter) 
{ 
    ... 
} 

जो इस तरह भस्म हो जाएगा:

MyResult result = MyMethod("someParameter"); 
if (!result.Success) 
{ 
    // an error occurred => use result.ErrorMessage to get more details 
} 
else 
{ 
    // everything went fine => use the result.SomeResult here 
} 

बेशक परिणाम के बजाय (जैसा कि इस उदाहरण में दिखाया गया है) एक स्ट्रिंग किसी अन्य जटिल वस्तु हो सकता है।

0

आप 3 गुणों के साथ कक्षा क्यों नहीं बनाते हैं। सफलता (बूल), संदेश (स्ट्रिंग) और टोकन (स्ट्रिंग)। आप उस वर्ग का एक उदाहरण बना सकते हैं, मानों को पॉप्युलेट कर सकते हैं और उसे वापस कर सकते हैं।

0

आप 2 वस्तुओं लौटना चाहते हैं, तो आप कुछ इस तरह कर सकते हैं:

private bool TestThing(out string errorMessage) 
    { 
     bool error = true; 
     if(error) 
     { 
      errorMessage = "This is a message!"; 
      return false; 
     } 

     errorMessage = ""; 
     return true; 
    } 

तो आप bool और त्रुटि संदेश

1

आप निश्चित रूप से सही हैं कि बाहरी भंडारण स्थान (उदाहरण के लिए एक सत्र चर) का उपयोग करके गलत तरीका है।

सही दृष्टिकोण इस बात पर निर्भर करता है कि आप असाधारण परिस्थिति में त्रुटि मानते हैं या नहीं। यदि नहीं, तो शब्द Try के साथ अपने समारोह लगाकर और उसके हस्ताक्षर होने से उदाहरण ढांचे में सेट का पालन इस तरह दिखेगा:

public bool TryGetFacebookToken(<necessary parameters>, out string token) 
{ 
    ... set the token within the body and return true if it succeeded or false if it did not 
} 

यहाँ नोट करने के लिए महत्वपूर्ण बात यह है कि इस दृष्टिकोण आम तौर पर इस्तेमाल किया जाता है जब आप केवल परवाह करें कि ऑपरेशन ने काम किया है या नहीं (और आपको वास्तव में परवाह नहीं है क्यों यह विफल होने पर काम नहीं करता है) और इसकी उचित उम्मीद है कि यह नहीं हो सकता है।

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

यह आपके परिदृश्य को भी सरल बनाता है, क्योंकि आपको केवल एक स्ट्रिंग वापस करने की आवश्यकता है।

2

यदि सफल हो, तो मैं AccessToken स्ट्रिंग को वापस करना चाहता हूं, अगर मैं एक त्रुटि संदेश वापस नहीं करना चाहता हूं। ये दोनों तार हैं, इसलिए कोई समस्या नहीं है। लेकिन कोड के कॉलिंग पक्ष पर रिटर्न वैल्यू की जांच करते समय, आप इसे प्रभावी ढंग से कैसे कर सकते हैं?

सी # वास्तव में त्रुटि संदेशों का उपयोग नहीं करता है, हम exceptions का उपयोग करते हैं। ऐसा करने का सही तरीका सिर्फ एक अपवाद फेंकना है, और कॉलर को अनदेखा या पकड़ने दें।

यदि यह असफल होने के लिए "असाधारण" नहीं है (उदाहरण के लिए, यदि कुछ उपयोगकर्ताओं को टोकन और कुछ नहीं करते हैं), तो एक टोकन की अनुपस्थिति को इंगित करने के लिए एक नल स्ट्रिंग वापस करने का विकल्प होगा (और अभी भी एक फेंक दें "असाधारण" मामलों के लिए अपवाद जैसे फेसबुक से संपर्क करने में सक्षम नहीं, आदि)। मुझे नहीं लगता कि यह आपके लिए मामला है, क्योंकि आपकी उदाहरण विफलता में अपवाद वस्तु शामिल थी।

नीचे की रेखा, यह है कि आप आमतौर पर शीर्ष स्टैक (आमतौर पर, यूआई) के लिए अपवाद हैंडलिंग (पकड़) छोड़ देते हैं क्योंकि वर्तमान ऑपरेशन का सबसे अधिक संदर्भ है। अपवाद को पकड़ने, स्ट्रिंग में सुधार करने के लिए इसका कोई उपयोग नहीं है, और फिर इसके बदले में वापस लौटें - रास्ते में मूल्यवान अपवाद जानकारी खोना। बस कॉलर के बजाय अपवाद है, और वे तय कर सकते हैं कि उपयोगकर्ता को उस विफलता को कैसे पेश किया जाए (या एफबी एकीकरण के बिना आगे बढ़ना)।

यह स्पष्ट रूप से मज़ाक उड़ाया जाता है, लेकिन उम्मीद है कि भर में मेरी बात (कोड शब्दों से जोर से बोलता है) हो जाता है:

class Facebook { 
    ... 
    public string GetAccessToken(string username, string password) { 
     // can throw WebException if can't connect to FB 
     this.Connect(); 

     // returns null token if not a Facebook user 
     if (!this.IsUser(username)) return null; 

     // can throw ArgumentException if password is wrong 
     var fbInfo = this.GetInfo(username, password); 

     return fbInfo.AccessToken; 
    } 
    ... 
} 

class Page { 
    void Page_Load(object sender, EventArgs e) { 
     var fb = new Facebook(); 

     string accessToken; 
     try { 
     accessToken = fb.GetAccessToken(this.User.Name, this.txtPassword.Text); 
     } catch (WebException ex) { 
     Log(ex); 
     this.divError.Text = "Sorry, Facebook is down"; 
     // continue processing without Facebook 
     } catch (ArgumentException ex) { 
     // Don't log - we don't care 
     this.divError.Text = "Your password is invalid"; 
     // stop processing, let the user correct password 
     return; 
     } catch (Exception ex) { 
     Log(ex); 
     // Unknown error. Stop processing and show friendly message 
     throw; 
     } 

     if (!string.IsNullOrEmpty(accessToken)) { 
     // enable Facebook integration 
     this.FillFacebookWallPosts(accessToken); 
     } else { 
     // disable Facebook integration 
     this.HideFacebook(); 
     } 
    } 
} 
4

एक टपल का प्रयास करें?

public Tuple<bool, string> ReturnsBoolAndString() { 
    return Tuple.Create(false, "string"); 
} 
6

musefan के जवाब पर निर्माण करने के लिए, मैं एक ही पैटर्न पसंद है, लेकिन एक सामान्य परिणाम प्रकार के साथ तो मैं यह पूरे codebase में उपयोग कर सकते हैं:

public class Result 
{ 
    public bool Success { get; set; } 
    public string ErrorMessage { get; set; } 
} 

public class Result<T> : Result 
{ 
    public T Data; 
} 

एक कारण यह है कि मैं इस बनाम एक फेंकने की तरह अन्यथा डेटा लौटने वाले फ़ंक्शन से अपवाद यह है कि यह आपको उस संग्रह को उस संग्रह पर मैप करने में मदद करता है, जो त्रुटि संदेशों में अपवाद विवरण कैप्चर करता है, इसलिए आपको पूरी श्रृंखला को उड़ाने वाले एक आइटम पर अपवाद के बारे में चिंता करने की आवश्यकता नहीं है। यह एक फ्लैट डेटा फ़ाइल, जहां सफल लाइनों आगे बढ़ना चाहिए से बाहर पंक्तियों को पार्सिंग लेकिन किसी भी त्रुटि के लिए व्यक्तिगत रूप से निपटा जाना चाहिए इस तरह की स्थितियों के लिए अच्छा है:

public static Result<Thing> ParseThing(string line) 
{ 
    try 
    { 
      // Parse a Thing (or return a parsing error.) 
      return new Result<Thing> { Data = thing, Success = true }; 
    } 
    catch (Exception ex) 
    { 
      return new Result<Thing> { Data = null, Success = false, ErrorMessage = "..." }; 
    } 
} 

... 

var results = lines.Select(ParseThing); 

foreach (var result in results) 
{ 
    // Check result.Success and deal with successes/failures here. 
} 
बेशक

, आप अभी भी एक अपवाद बाहर फेंकने का विकल्प होता है प्रसंस्करण की पूरी श्रृंखला को उड़ाते समय वास्तव में असाधारण परिस्थितियों के लिए उस कार्य का वह वही है जो आप चाहते हैं।

पीएस हर दिन वह दिन होता है जब मैं चाहता हूं कि सी # में कई रिटर्न वैल्यू हों।

+0

वास्तव में इसमें अब कई रिटर्न मान हैं।आप टुपल या ट्यूपल इत्यादि का उपयोग कर सकते हैं। Https://msdn.microsoft.com/en-us/library/dd268536(v=vs.110).aspx – stefann

+0

देखें, एक भाषा निर्माण के रूप में सीधे एकाधिक रिटर्न मान, लुआ या गो की भावना में। (क्षमा करें, गोलपोस्ट को स्थानांतरित न करें।) कुछ ऐसा: सार्वजनिक बात, स्ट्रिंग पार्सिंग (...) {...} var thing, err = parseThing (...); मैंने वास्तव में इसे नहीं सोचा है, हालांकि; मुझे यकीन है कि अच्छे कारण हैं कि यह भाषा के साथ क्यों फिट नहीं होगा। – user1454265

+0

मुझे पता है कि आपका क्या मतलब है और सहमत हैं। यह ट्यूपल निर्माण के शीर्ष पर सिंटेक्टिक चीनी हो सकता है। आपको विजुअल स्टूडियो के माध्यम से एक सुझाव दर्ज करना चाहिए। – stefann

2

एक अधिक सामान्य कार्यान्वयन

सी #

public class ReturnMessage<T> 
{ 
    //indicates success or failure of the function 
    public bool IsSuccess { get; set; } 
    //messages(if any) 
    public string Message { get; set; } 
    //data (if any) 
    public T Data { get; set; } 
} 

VB.NET

Public Class ReturnMessage(Of T) 
    'indicates success or failure of the function 
    Public Property IsSuccess As Boolean 
    'messages(if any) 
    Public Property Message As String 
    'data (if any) 
    Public Property Data As T 
End Class 

इस विधि से एक कैच ब्लॉक में ex.Message और Data<T> कोशिश ब्लॉक में पारित कर सकते हैं हो जाएगा

संबंधित मुद्दे