簡體   English   中英

為什么我允許傳遞比我為該方法定義的參數更多的參數?

[英]Why am I allowed to pass in more parameters than I defined for the method?

我正在嘗試學習一個使用C#的名為Xamarin的移動開發框架,我也是一個初學者。 當我遇到以下代碼時,我正在關注一個教程:

public static class PhonewordTranslator
{
    public static string ToNumber(string raw)
    {
        if (string.IsNullOrWhiteSpace(raw))
        {
            return "";
        }
        else
        {
            raw = raw.ToUpper();
        }
        var newNumber = new StringBuilder();
        foreach (var c in raw)
        {
            if (" -0123456789".Contains(c))
            {
                newNumber.Append(c);
            }
            else
            {
                var result = TranslateToNumber(c);
                if (result != null)
                {
                    newNumber.Append(result);
                }
            }
        }
        return newNumber.ToString();
    }
    static bool Contains (this string keyString, char c)
    {
        return keyString.IndexOf(c) >= 0;
    }
    static int? TranslateToNumber(char c)
    {
        if ("ABC".Contains(c))
            return 2;
        else if ("DEF".Contains(c))
            return 3;
        else if ("GHI".Contains(c))
            return 4;
        else if ("JKL".Contains(c))
            return 5;
        else if ("MNO".Contains(c))
            return 6;
        else if ("PQRS".Contains(c))
            return 7;
        else if ("TUV".Contains(c))
            return 8;
        else if ("WXYZ".Contains(c))
            return 9;
        return null;
    }

為什么我允許將一個參數傳遞給Contains()方法,即使它顯然具有兩個參數也是如此。 這樣做的目的是什么?

Contains()方法就是所謂的擴展方法。 您可以在此處找到有關它們的更多信息

在您的代碼中, Contains方法定義為Extension Method

那么什么是擴展方法

擴展方法使您可以將方法“添加”到現有類型,而無需創建新的派生類型,重新編譯或修改原始類型。 擴展方法是一種特殊的靜態方法,但是它們的調用就像是擴展類型上的實例方法一樣。

以及它們如何工作?

擴展方法定義為靜態方法,但使用實例方法語法調用。 它們的第一個參數指定方法將對哪種類型進行操作,並且此參數之前帶有this修飾符。

在您的代碼中,您將使用實例方法語法調用擴展方法。 但是,編譯器生成的中間語言(IL)將您的代碼轉換為對靜態方法的調用。

讓我們通過一個例子來理解這一點。

眾所周知,如果我們通過調用ToString方法將null object轉換為string ,那么它將拋出NullReferenceException 雖然我可以調用Convert.ToString()方法,該方法不會為null值引發異常。 但是,如果我想像語法一樣堅持使用ToString方法,該怎么辦? 因此,在需要將任何object轉換為string值的object上調用ToString方法之前,首先需要檢查null ,然后將其轉換為string值。 但這很耗時,我必須為此編寫代碼。

為了克服這個問題,我創建了一個名為ToStringNullSafeExtensionMethod 首先要檢查object null值。 如果null則將其轉換為Empty String否則將object值轉換為string值。

這是我的擴展方法的定義

 public static string ToStringNullSafe(this object obj)
 {
      return (obj ?? string.Empty).ToString();
 }

這就是調用語法

DataRow dr = dataTable.Rows[0];
string firstName = dr["firstName"].ToStringNullSafe();

創建ExtensionMethod需要考慮的一件事是ExtentionMethod名稱應與.Net框架中提供的方法不同。 就像我們有ToString方法進行string轉換一樣。 因此,我無法使用此名稱創建擴展方法。

如果我使用.Net框架方法名稱作為擴展名創建擴展方法,那么不會出現編譯器錯誤,但是不會調用您創建的ExtensionMethod 假設如果我通過將擴展名定義為ToString創建擴展方法,則編譯器將不會調用我的擴展方法。 它將調用.Net框架提供的ToString方法。

在Visual Studio中, ExtensionMethosDown Arrow標志出現

在此處輸入圖片說明

擴展方法可以放在單獨的類中,例如我有一個擴展方法可以將DataTable轉換為單獨類中的string[][] array

namespace myProject.Common
{
    public static class ExtensionMethods
    {
        public static object ToStringArray(this DataTable dt, params string[] columns)
        {
           //AsEnumerable is also a Extension Method provided by .Net framework.
           return dt.AsEnumerable().Select(x => columns.Select(c => x[c].ToStringNullSafe()).ToArray()).ToArray();

        }
    }
    public static string ToStringNullSafe(this object obj)
    {
        return (obj ?? string.Empty).ToString();
    }
}

要在我的項目中使用此ExtensionMethod ,我必須先添加using語句

using myProject.Common;

然后我可以按以下方式調用此方法:

var dataTableData = dataTable.ToStringArray("firstName", "LastName", "Age", "Email");

調用擴展方法的另一種語法是:

 var dataTableData = ExtensionMethods.ToStringArray(dataTable,"firstName", "LastName", "Age", "Email");

進一步閱讀:

  1. 擴展方法
  2. 創建ToString的擴展方法?
  3. 擴展方法的優點
  4. 擴展方法的缺點

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM