为什么我允许传递的参数多于我为方法定义的参数?

时间:2017-10-09 04:50:45

标签: c# android xamarin parameter-passing

我正在尝试学习一个名为Xamarin的移动开发框架,它使用C#,我也是初学者。当我遇到以下代码时,我正在学习教程:

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()方法,即使它显然有两个参数。这是什么目的?

2 个答案:

答案 0 :(得分:2)

Contains()方法是什么叫做扩展方法。您可以找到有关他们的更多信息here.

答案 1 :(得分:0)

在您的代码Contains中,方法定义为Extension Method

那么什么是扩展方法

  

扩展方法可让您添加"现有类型的方法,无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为扩展类型的实例方法。

它们是如何工作的?

  

扩展方法被定义为静态方法,但是通过使用实例方法语法来调用。它们的第一个参数指定方法操作的类型,参数前面有this修饰符。

     

在您的代码中,您使用实例方法语法调用扩展方法。但是,编译器生成的中间语言(IL)会将您的代码转换为静态方法的调用。

让我们通过一个例子理解这一点。

众所周知,如果我们通过调用object方法将null string转换为ToString,则会抛出NullReferenceException。虽然我可以调用Convert.ToString()方法,但不会为null值抛出异常。但是如果我想坚持ToString方法就像语法一样。因此,在需要转换为ToString值的任何object上调用string方法之前,首先我需要检查null然后将其转换为string值。但这很耗时,我必须为它编写代码。

为了解决这个问题,我创建了一个名为ExtensionMethod的{​​{1}}。它将首先检查ToStringNullSafe的{​​{1}}值。如果它具有null值,则会将其转换为object,否则会将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方法。

在visual studio中,ToString

会显示.Net符号

enter image description here

扩展方法可以放在单独的类中,就像我有一个扩展方法,可以在一个单独的类中将Down Arrow转换为ExtensionMethos

DataTable

要在我的项目中使用此string[][] array,我必须首先添加一个using语句

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 myProject.Common;

进一步阅读:

  1. Extension Methods
  2. Creating an extension method for ToString?
  3. Advantages of Extension Methods
  4. Disadvantages of extension methods