0

I'm trying to learn a mobile development framework called Xamarin that uses C#, which I am a beginner at as well. I was following a tutorial when I came across the following code:

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;
    }

Why am I allowed to pass in a single parameter to the Contains() method even though it clearly has two parameters. What is the purpose of this?

Jimmy12201
  • 41
  • 4
  • 5
    Contains is an extension method. The first parameter is the object on which the method will be called (notice `this` keyword in the first parameter) and other parameters are the actual parameters. You need to read about extension methods. – Chetan Oct 09 '17 at 04:54

2 Answers2

2

The Contains() method is whats known as an extension method. You can find more information about them here.

Sylvoo
  • 265
  • 2
  • 17
0

In your code Contains method is defined as Extension Method.

So what are Extension Methods

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

And how they work?

Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the this modifier.

In your code you invoke the extension method with instance method syntax. However, the intermediate language (IL) generated by the compiler translates your code into a call on the static method.

Lets understand this with an example.

As you all know if we convert an object which is null to string by calling ToString method then it throws NullReferenceException. Though I can call Convert.ToString() method which doesn't throw exception for null value. But what if I want to stick ToString method like syntax. So before calling ToString method on any object that need to be converted to stringvalue, First i need to check for null and then convert it to string value. But it is time consuming and i have to write code for it.

To overcome this i have created a ExtensionMethod named as ToStringNullSafe. It is going to first check for null value of object. If it has null value then it will convert it to an Empty String otherwise converts object value to a string value.

This is the definition of the my Extension method

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

And this is the calling syntax

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

One thing need to consider while creating a ExtensionMethod is that ExtentionMethod name should differ from the method present in .Net framework. Like we have ToString method for string conversion. So i can't create a extension method with this name.

What if i create an extension method with name as of .Net framework method name then there will not be compiler errors but your created ExtensionMethod will not be called. Suppose if i create an extension method by defining its name as ToString then compiler will not invoke my extension method. It will invoke ToString method provided by .Net framework.

In visual studio a Down Arrow sign appears for ExtensionMethos

enter image description here

Extension Methods can be placed in separate class like i have an Extension Method to convert a DataTable to string[][] array in a separate class.

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();
    }
}

To use this ExtensionMethod in my project, i have to add an using statement first

using myProject.Common;

then i can call this method as follow:

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

Another syntax of calling extension method is;

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

Further Reading:

  1. Extension Methods
  2. Creating an extension method for ToString?
  3. Advantages of Extension Methods
  4. Disadvantages of extension methods
Community
  • 1
  • 1
mmushtaq
  • 3,430
  • 7
  • 30
  • 47