أيهما أفضل، وذلك باستخدام + من المعلمة وقيم الفارغة أو العودة منطقية

StackOverflow https://stackoverflow.com/questions/1800003

  •  05-07-2019
  •  | 
  •  

سؤال

ودعونا نقول لدي وظيفة التي تحتاج إلى إعادة بعض قيمة عددية. ولكن يمكن أيضا أن تفشل، وأريد أن أعرف عندما تفعل ذلك.

ما هو أفضل وسيلة؟

public int? DoSomethingWonderful()

أو

public bool DoSomethingWonderful(out int parameter)

وهذا هو على الارجح أكثر من سؤال النمط، ولكن ما زلت غريبة الخيار الذي كان الناس تأخذ.

وتحرير: (... يتيح نسميها سحابة لا، صندوق أسود لا، انتظر سحابة نعم.) التوضيح، هذا الرمز إلى محادثات صندوق أسود. أنا لا يهمني <م> لماذا فشلت. وأود أن الحاجة فقط أن أعرف إذا كان لدي قيمة صالحة أم لا.

هل كانت مفيدة؟

المحلول

وأنا أحب نسخة قيم الفارغة أفضل، لأنه يمكنك استخدام المشغل لاغية تتجمع ؟؟ على ذلك، منها مثلا:

int reallyTerrible = 0;
var mightBeWonderful = DoSomethingWonderful() ?? reallyTerrible;

نصائح أخرى

على ان ذلك يعتمد على كيفية تفكيرك رمز الدعوة يجب أن تبدو. و بالتالي ما يتم استخدام الدالة لديك.

وعموما، يجب تجنب من الحجج. من ناحية أخرى، يمكن أن يكون من الجميل أن يكون رمز مثل هذا:

int parameter;
if (DoSomething(out paramameter))
{
  // use parameter
}

وعندما يكون لديك كثافة قيم الفارغة، فإنه تبدو مثل هذا:

int? result = DoSomething();
if (result != null)
{
  // use result
}

وهذا هو أفضل نوعا ما لأنك لم يكن لديك حجة، ولكن الرمز الذي يقرر إذا كانت وظيفة نجح لا تبدو واضحة جدا.

ولا ننسى أن هناك خيار آخر: استخدام Exeptions. القيام بذلك فقط إذا كانت القضية حيث فشلت وظيفة الخاص بك هو حقا استثنائي ونوع من حدة الخطأ.

try
{
  // normal case
  int result = DoSomething()
}
catch (SomethingFailedException ex)
{
  // exceptional case
}

وميزة واحدة من الاستثناء هو أنه لا يمكن تجاهله. الحالة الطبيعية هي أيضا على التوالي إلى الأمام لتنفيذها. إذا كانت القضية استثنائية شيء يمكن أن تتجاهل، يجب عدم استخدام الاستثناءات.

تعديل: هل نسيت أن أذكر: ميزة أخرى لاستثناء هي أنك يمكن أن توفر أيضا معلومات <م> لماذا فشلت العملية. يتم توفير هذه المعلومات من قبل نوع الاستثناء، خصائص استثناء ونص الرسالة.

لماذا لا رمي استثناء؟

وأود أن تتبع نمط استخدامها في مكان ما في المكتبة صافي مثل:

bool int.TryParse(string s, out value)
bool Dictionary.TryGetValue(T1 key, out T2 value)

وهكذا أود أن أقول:

public bool TryDoSomethingWonderful(out int parameter)

وانها حقا يتوقف على ما تقومون به.

هل لاغيا إجابة ذات معنى؟ إن لم يكن، أنا يفضل استدعاء أسلوب bool TryDoSomethingWonderful(out int). هذا يتطابق مع الإطار.

إذا، ومع ذلك، لاغية هو قيمة الإرجاع ذات مغزى، الباحث عودته؟ من المنطقي.

وإذا لم الأداء هو الشاغل الرئيسي يجب إرجاع int ورمي استثناء على الفشل.

وأود أن استخدام ثاني، لأنني ربما تحتاج إلى معرفة الحق بعيدا إذا نجحت الدعوة، وفي هذه الحالة أود أن أكتب بدلا

int x;
if( DoSomethingWonderful( out x ) )
{
    SomethingElse(x);
}

من

int? x = DoSomethingWonderful();
if( x.HasValue )
{
   SomethingElse(x.Value);
}

وأنا أؤيد استخدام معلمة إخراج. في رأيي، وهذا هو النوع من الحالات التي استخدامها لمعلمات الإخراج هو الأكثر ملاءمة.

نعم، يمكنك استخدام المشغل تتجمع للحفاظ على التعليمات البرمجية باعتباره احد بطانة إذا وفقط إذا كان لديك قيمة البديلة التي يمكن استخدامها في بقية التعليمات البرمجية. كثيرا ما أجد أن الأمر ليس كذلك بالنسبة لي، وأنا أفضل أن تنفيذ مسار رمز مختلف مما كنت لو كنت بنجاح قادرا على استرداد قيمة.

        int value;
        if(DoSomethingWonderful(out value))
        {
            // continue on your merry way
        }
        else
        {
            // oops
            Log("Unable to do something wonderful");

            if (DoSomethingTerrible(out value))
            {
                // continue on your not-so-merry way
            }
            else
            {
                GiveUp();
            }
        }

وبالإضافة إلى ذلك، إذا كانت القيمة التي أريد لاسترداد هي قيم الفارغة في الواقع، ثم باستخدام وظيفة مع معلمة الإخراج وقيمة إرجاع منطقية هو، في رأيي، وأسهل طريقة لمعرفة الفرق بين "أنا لم يوفق في استرجاع القيمة "و" قيمة I استرجاع فارغة ". أحيانا ما يهمني هذا التمييز، كما هو الحال في المثال التالي:

    private int? _Value;
    private bool _ValueCanBeUsed = false;

    public int? Value
    {
        get { return this._Value; }
        set
        {
            this._Value = value;
            this._ValueCanBeUsed = true;
        }
    }

    public bool DoSomethingTerrible(out int? value)
    {
        if (this._ValueCanBeUsed)
        {
            value = this._Value;
            // prevent others from using this value until it has been set again
            this._ValueCanBeUsed = false;
            return true;
        }
        else
        {
            value = null;
            return false;
        }
    }

في رأيي، والسبب الوحيد لمعظم الناس لا يميلون إلى استخدام معلمات الإخراج لأنهم العثور على جملة مرهقة. ومع ذلك، أشعر حقا أن استخدام معلمات الإخراج هو الحل الأنسب لهذه المشكلة، ووجدت أنه بمجرد أن اعتدنا عليه وجدت بناء الجملة أفضل بكثير لإرجاع قيمة خالية.

إذا لا يوجد سوى طريقة واحدة يمكن أن تفشل، أو إذا كنت لن تحتاج إلى معرفته <م> لماذا فشلت، وانا اقول انها ربما أبسط وأسهل للذهاب مع قيمة الإرجاع قيم الفارغة.

وعلى العكس من ذلك، إذا كان هناك عدة طرق يمكن أن تفشل، ورمز الدعوة يمكن أن تريد أن تعرف بالضبط لماذا فشلت، ثم انتقل مع المعلمة خارج والعودة رمز خطأ بدلا من منطقي (بدلا من ذلك، هل يمكن رمي استثناء ، ولكن على أساس سؤالك، يبدو أنك قد قررت بالفعل عدم رمي استثناء).

ويجب عليك بدلا من استخدام الصيد المحاولة. هذا يبدو وكأنه المتصل لا يعرف ما يمكن أن يحدث؟

هل علينا التحقق من كل منطقي وخارج، أو ينبغي أن تحقق عوائد على حد سواء لاغية والعودة الفعلية.

واسمحوا طريقة تفعل ما ينبغي، وفي حال فشلت، والسماح للالمتصل يعرف أنها فشلت، وhanlde المتصل كما requied.

ومن المثير للاهتمام، رأيي الشخصي يترنح تستند إلى حد كبير على طبيعة الأسلوب. على وجه التحديد، اذا كان الغرض الطريقة هو استرداد قيمة واحدة ، ومعارضة "تفعل شيئا".

مثال:

bool GetSerialNumber(out string serialNumber)

ومقابل

string GetSerialNumber() // returns null on failure

والثانية يشعر أكثر "طبيعية" بالنسبة لي بطريقة أو بأخرى، وكذلك:

bool GetDeviceId(out int id)

ومقابل

int? GetDeviceId() // returns null on failure`

ولكن أعترف هذا يندرج حقا في "الترميز أسلوب" الأرض.

وأوه، وأنا أيضا سوف تميل لصالح رمي استثناء:

int GetDeviceId() // throws an exception on read failure

وأنا ما زلت لا تباع لماذا لديهم من الخطأ جدا. يمكن لدينا موضوع على ذلك، أورين؟ ؛ -)

ولم يعجبني مايكروسوفت نمط "حاول" التي يتم فيها استخدام "خارج" المعلمة لإرجاع البند البيانات. من بين أمور أخرى، طرق مشفرة على هذا النحو لا يمكن أن تستخدم في واجهات التغاير. ولكنني أرى طريقة ترميز على النحو التالي: T GetValue(out bool Successful) أو ربما T GetValue(out GetValueErrorEnum result); أو T GetValue(out GetValueErrorInfo result); إذا قد تكون هناك حاجة إلى شيء ما وراء صح / خطأ. لأن كل نوع بيانات له قيمة افتراضية القانونية، وليس هناك مشكلة مع اتخاذ قرار بشأن ما للعودة إذا فشل وظيفة. رمز الهاتف يمكن القول بسهولة:

  bool success;
  var myValue = Thing.GetValue(ref success);
  if (success)
    .. do something using myValue
  else
    .. ignore myValue

وسيكون من الجميل لو صافي وC # تقدم التغاير الحقيقي "نسخ من" المعلمات (الطالب أن تخصيص مساحة للنتيجة، تمرير مؤشر إلى تلك المساحة إلى استدعاء الدالة، ثم قم بنسخ المساحة المخصصة التي تم تمريرها متغير -in فقط بعد عودة وظيفة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top