Przeciążanie metod w C#

Przeciążanie metod w C#

Przeciążanie metod w C# z przykładami

W tym artykule omówię Co to jest przeciążanie metod w C# i jaki jest pożytek z przeciążania metod w tworzeniu naszych aplikacji za pomocą przykładów. Przeczytaj nasz poprzedni artykuł przed przejściem do tego artykułu, w którym omówiliśmy podstawy polimorfizmu w C# . Na końcu tego artykułu będziesz miał bardzo dobre zrozumienie następujących wskazówek związanych z przeciążaniem metod.

  1. Co to jest przeciążanie metod w C#?
  2. Kiedy powinniśmy przeciążać metody?
  3. Jakie są zalety używania przeciążania metod w C#?
  4. Kiedy metoda jest uważana za metodę przeciążoną?
  5. Co to jest przeciążanie metody opartej na dziedziczeniu?
  6. Scenariusze czasu rzeczywistego, w których musisz użyć przeciążania metod?
  7. Co to jest przeciążanie konstruktora w C#?
  8. Przykładowe rejestrowanie w czasie rzeczywistym przy użyciu przeciążania metod w C#?

Uwaga: Punkt, o którym należy pamiętać, to przeciążanie funkcji i terminy przeciążania metod są używane zamiennie. Przeciążanie metod jest jednym z najczęstszych sposobów implementacji polimorfizmu w czasie kompilacji w C#.

Co to jest przeciążanie metod lub przeciążanie funkcji w C#?

Przeciążanie metod oznacza, że ​​jest to podejście do definiowania wielu metod w ramach klasy o jednej nazwie. Tak więc możemy zdefiniować w klasie więcej niż jedną metodę o tej samej nazwie. Ale punkt, w którym musisz zapamiętać parametry wszystkich tych metod, powinien być inny (różny pod względem liczby, typu i kolejności parametrów).

Tak więc, jeśli definiujemy wiele metod o tej samej nazwie, ale z innym podpisem w klasie lub w klasach nadrzędnej i podrzędnej, to w języku C# nazywa się to przeciążaniem metod. Oznacza to, że C#.NET umożliwia nie tylko przeciążanie metod w tej samej klasie, ale także umożliwia przeciążanie metod w klasach nadrzędnych i podrzędnych. Tak więc możemy utworzyć metodę w klasie Derived/Child o tej samej nazwie, co nazwa metody zdefiniowana w klasie Base/Parent w C#.

W prostych słowach możemy powiedzieć, że przeciążanie metod w C# pozwala klasie mieć wiele metod o tej samej nazwie, ale o innej sygnaturze. Funkcje lub metody mogą być przeciążane na podstawie liczby, typu (int, float itp.), kolejności i rodzaju (Value, Ref lub Out) parametrów. Aby lepiej zrozumieć, spójrz na poniższy obraz. Wszystkie metody będą poprawne i na podstawie wywołania metody kompilator automatycznie zdecyduje, która przeciążona wersja ma zostać wywołana.

Jak widać na powyższym obrazku, wszystkie metody mają tę samą nazwę, tj. Metoda, ale z różnymi parametrami. Jeśli spojrzysz na dwie pierwsze metody, liczba parametrów jest inna. Pierwsza metoda przyjmuje zero parametrów, podczas gdy druga metoda przyjmuje jeden parametr. Następnie, jeśli porównasz drugą metodę z trzecią, obie przyjmują tę samą liczbę parametrów, ale różnych typów. Druga metoda przyjmuje parametr w postaci liczby całkowitej, podczas gdy metoda trzecia przyjmuje parametr ciągu. Ponadto, jeśli porównasz czwartą i piątą metodę, obie mają tę samą liczbę parametrów, ale kolejność parametrów jest inna. Czwarta metoda przyjmuje pierwszy parametr jako liczbę całkowitą, a drugi parametr jako ciąg, podczas gdy metoda piąta przyjmuje pierwszy parametr jako ciąg, a drugi parametr jako liczbę całkowitą. Tak więc każda metoda różni się pod względem liczby, typu i kolejności parametrów, co w C# nazywa się przeciążaniem metod.

Podpis metody składa się z nazwy metody oraz typu danych, liczby, kolejności i rodzaju (wartość, referencja lub wyjście) parametrów. Należy pamiętać, że podpis metody nie zawiera typu zwracanego i modyfikatorów params. Dlatego nie jest możliwe przeciążenie metody tylko na podstawie zwracanego typu i modyfikatora params. Modyfikator Params omówimy w naszym nadchodzącym artykule.

Przykład zrozumienia przeciążania metod w C#:
using System;
namespace MethodOverloading
{
    class Program
    {
        static void Main(string[] args)
        {
            Program obj = new Program();
            obj.Method(); //Invoke the 1st Method
            obj.Method(10); //Invoke the 2nd Method
            obj.Method("Hello"); //Invoke the 3rd Method
            obj.Method(10, "Hello"); //Invoke the 4th Method
            obj.Method("Hello", 10); //Invoke the 5th Method

            Console.ReadKey();
        }

        public void Method()
        {
            Console.WriteLine("1st Method");
        }
        public void Method(int i)
        {
            Console.WriteLine("2nd Method");
        }
        public void Method(string s)
        {
            Console.WriteLine("3rd Method");
        }
        public void Method(int i, string s)
        {
            Console.WriteLine("4th Method");
        }
        public void Method(string s, int i)
        {
            Console.WriteLine("5th Method");
        }    
    }
}
Wyjście:

Dlaczego typ zwrotu nie jest uważany za część przeciążania metod w C#?

Za pomocą przykładu zrozummy, dlaczego typ zwracany nie jest uważany za część przeciążania metody. Proszę spojrzeć na poniższy obraz. Tutaj napisałem dwie metody o tej samej nazwie, ale typem zwracanym jednej metody jest void, a typem zwracanym drugiej metody jest string. Zobacz, jak tylko utworzymy drugą metodę, sam kompilator wyświetla błąd czasu kompilacji, mówiąc Typ „Program” już definiuje element członkowski o nazwie „Metoda” z tymi samymi typami parametrów.

Więc w momencie definiowania metody tylko kompilator dał nam błąd. Teraz nadal możesz mieć wątpliwości, typy zwrotów są różne, więc dlaczego ma być nieważne. Aby zrozumieć, spróbujmy wywołać metodę, jak pokazano na poniższym obrazku. Więc kiedy wywołujemy metodę, czy możesz mi powiedzieć, która wersja metody zostanie wywołana? Ponieważ mamy dwie metody, które nie przyjmują żadnych parametrów. Tak więc, tutaj dostaniemy problem niejednoznaczności i zobaczymy, że kompilator również podaje ten sam błąd niejednoznaczności Wywołanie jest niejednoznaczne między następującymi metodami lub właściwościami:'Program.Method()' i 'Program.Method()' podczas wywoływania metody.

Mimo to masz wątpliwości, typy zwrotów są różne. Zobacz, typy zwracane pojawiają się na obrazku pod koniec wykonywania metody. Ale tutaj zamieszanie nie jest na końcu wykonywania metody, ale zamieszanie dotyczy tego, od czego zacząć i którą metodę należy wywołać. Tak więc kompilator nie ma jasności, aby rozpocząć wykonywanie metody, a mówienie o końcu wykonywania metody nie ma żadnego sensu. To jest powód, dla którego zwracany typ nigdy nie jest brany pod uwagę podczas definiowania przeciążania metod w C#.

Kiedy powinniśmy przeciążać metody w C#?

Zrozumieliśmy, co to jest przeciążanie metod i jak zaimplementować przeciążanie metod w C#. Ale ważne pytanie brzmi, kiedy musimy wdrożyć lub kiedy musimy przejść do przeciążania metod w C#. Rozumiemy to na przykładzie.

Koncepcja przeciążania metod podlega zasadzie OOP polimorfizmów. Programowanie obiektowe opiera się na czterech zasadach, tj. enkapsulacji, abstrakcji, dziedziczeniu i polimorfizmie.

Co to jest polimorfizm? Polimorfizm to mechanizm zmiany zachowania na podstawie danych wejściowych. Oznacza to, że gdy zmienia się wejście, automatycznie zmienia się wyjście lub zachowanie. Najlepszym przykładem polimorfizmu jesteśmy my sami. Na przykład, kiedy słyszymy coś interesującego lub coś, co jest dla nas dobre, czujemy się szczęśliwi. A kiedy słyszymy coś, co nie jest dla nas dobre, jest nam smutno. Załóżmy, że poprosiłeś ojca, aby kupił rower, a jeśli twój ojciec kupi rower dla ciebie, będziesz szczęśliwy. A jeśli twój ojciec powie, że nie kupię ci roweru, to będzie ci smutno. Więc jesteś tą samą osobą, kiedy otrzymałeś coś dobrego, czujesz się szczęśliwy, a kiedy otrzymujesz coś, co nie jest dobre, czujesz się smutny. Nazywa się to polimorfizmem. Zachowanie się na różne sposoby w oparciu o otrzymane dane wejściowe, tj. za każdym razem, gdy dane wejściowe się zmienią, dane wyjściowe zmieniają się automatycznie.

Tutaj zmiany danych wejściowych oznaczają, że nie myśl, że wartości się zmieniają. Zmiany danych wejściowych oznaczają, że gdy zmienimy numer, typ i kolejność wprowadzania, wartości zostaną zmienione. Nie myśl, że jeśli zdam 10, dostanę wartość, jeśli zdam 20, dostanę inną wartość. W tym celu, jeśli warunek inny jest wystarczający, przeciążanie nie jest wymagane. Kiedy spodziewasz się, że dane wyjściowe zostaną zmienione na podstawie liczby, typu i kolejności danych wejściowych, wystarczy przejść do Przeciążania metod w C#.

Aby lepiej zrozumieć, spójrz na poniższy przykład. Tutaj stworzyliśmy trzy metody o tej samej nazwie, aby wykonać dodawanie dwóch liczb całkowitych, dwóch zmiennoprzecinkowych i dwóch łańcuchów. Tak więc, gdy podamy dwie liczby całkowite, otrzymamy jedno wyjście, a gdy podamy dwie wartości łańcuchowe, otrzymamy inne wyjście i podobnie, gdy podamy dwie liczby zmiennoprzecinkowe, otrzymamy kolejne wyjście. Oznacza to, że gdy dane wejściowe zmieniają się, dane wyjściowe lub zachowanie również ulegają automatycznej zmianie. Nazywa się to polimorfizmem w C#.

using System;
namespace MethodOverloading
{
    class Program
    {
        public void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        public void Add(float x, float y)
        {
            Console.WriteLine(x + y);
        }
        public void Add(string s1, string s2)
        {
            Console.WriteLine(s1 +" "+ s2);
        }
        static void Main(string[] args)
        {
            Program obj = new Program();
            obj.Add(10, 20);
            obj.Add(10.5f, 20.5f);
            obj.Add("Pranaya", "Rout");
            Console.ReadKey();
        }
    }
}
Wyjście:

Załóżmy, że jesteś użytkownikiem klasy Program i podczas tworzenia instancji klasy Program i po wpisaniu nazwy obiektu i operatora kropki nie zobaczysz trzech różnych metod Add , zobaczysz tylko jedną metodę Add z dwiema przeciążonymi wersjami metody Add, jak pokazano na poniższym obrazku.

Zaletą stosowania przeciążania metod jest więc to, że jeśli przeciążamy metody, to użytkownik naszej aplikacji ma poczucie komfortu w korzystaniu z metody z wrażeniem, że on/ona wywołanie jednej metody przez przekazanie różnych typów wartości. Najlepszym przykładem dla nas jest zdefiniowany przez system „WriteLine() " metoda. Jest to metoda przeciążona, a nie pojedyncza metoda przyjmująca różne typy wartości. Jeśli przejdziesz do definicji klasy Console, zobaczysz następujące przeciążone wersje metody WriteLine zdefiniowanej w klasie Console.

Kiedy metoda jest uważana za metodę przeciążoną w C#?

Jeśli dwie metody mają tę samą nazwę metody, ale mają różne sygnatury, to te metody są uważane za metody przeciążone. Następnie regułą, którą powinniśmy sprawdzić, jest to, że obie metody muszą mieć inny parametr Typy/Liczby/Zamówienia . Ale nie ma reguły dotyczącej typu zwracanego, specyfikatora dostępu i modyfikatora dostępu oznacza, że ​​metody przeciążania mogą mieć swój własny typ zwracany (void, float, int, string itp.), własny specyfikator dostępu (publiczny, prywatny, chroniony itp.) i modyfikator dostępu (zapieczętowany, statyczny, wirtualny itp.), ponieważ metody przeciążania są różnymi metodami

Czy możemy przeciążać metody w tej samej klasie?

Tak, to możliwe. Brak błędu czasu kompilacji i brak błędu w czasie wykonywania. Metody mogą być przeciążone w tej samej lub w klasach nadrzędnych i podrzędnych, ponieważ metody przeciążone są różnymi metodami. Ale nie możemy nadpisać metody w tej samej klasie, która prowadzi do błędu czasu kompilacji:„Metoda jest już zdefiniowana ”, ponieważ nadrzędne metody to te same metody z inną implementacją. W naszym następnym artykule omówimy zastępowanie metody w C# z przykładami.

Co to jest przeciążanie metod opartych na dziedziczeniu w C#?

Metoda zdefiniowana w klasie nadrzędnej może być również przeciążona w jej klasie podrzędnej. Nazywa się to przeciążaniem metod opartych na dziedziczeniu w języku C#. Zobacz poniższy przykład, aby lepiej zrozumieć. Jak widać w poniższym kodzie, dwukrotnie zdefiniowaliśmy metodę Add w klasie Class1 oraz zdefiniowaliśmy metodę Add w klasie potomnej Class1. Zauważ, że każda metoda Add przyjmuje różne typy parametrów.

using System;
namespace MethodOverloading
{
    class Class1
    {
        public void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        public void Add(float x, float y)
        {
            Console.WriteLine(x + y);
        }
    }
    class Class2 : Class1
    {
        public void Add(string s1, string s2)
        {
            Console.WriteLine(s1 +" "+ s2);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Class2 obj = new Class2();
            obj.Add(10, 20);
            obj.Add(10.5f, 20.7f);
            obj.Add("Pranaya", "Rout");
            Console.ReadKey();
        }
    }
}
Wyjście:

Uwaga: Aby przeciążyć metodę klasy nadrzędnej pod jej klasą potomną, klasa potomna nie wymaga żadnych uprawnień od swojej klasy nadrzędnej.

Scenariusz czasu rzeczywistego, w którym można użyć przeciążania metod w C#

Załóżmy, że pracujesz nad projektem konserwacji. I będziesz pracować nad klasą, w której zdefiniowano już kilka sparametryzowanych konstruktorów i musisz przekazać kilka dodatkowych parametrów. Więc co zrobisz, czy dodasz wymagany parametr za pomocą jednego z już zdefiniowanych konstruktorów, czy dodasz nowy konstruktor zgodnie z wymaganiami? W takich przypadkach nie należy dodawać wymaganego parametru za pomocą już zdefiniowanego konstruktora, ponieważ może to zakłócić inną strukturę zależności klas. To, co zrobisz, to utworzenie nowego konstruktora z wymaganym parametrem. Ten nowy konstruktor, który tworzysz, to nic innego jak przeciążenie konstruktora w C#.

Przykład zrozumienia przeciążenia metody konstruktora w C#

Proszę spojrzeć na poniższy przykład. Tutaj tworzymy trzy różne wersje konstruktora, a każdy konstruktor przyjmuje inną liczbę parametrów, co w C# nazywa się przeciążaniem konstruktora.

using System;
namespace ConstructorOverloading
{
    class ConstructorOverloading
    {
        int x, y, z;
        public ConstructorOverloading(int x)
        {
            Console.WriteLine("Constructor1 Called");
            this.x = 10;
        }
        public ConstructorOverloading(int x, int y)
        {
            Console.WriteLine("Constructor2 Called");
            this.x = x;
            this.y = y;
        }
        public ConstructorOverloading(int x, int y, int z)
        {
            Console.WriteLine("Constructor3 Called");
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public void Display()
        {
            Console.WriteLine($"X={x}, Y={y}, Z={z}");
        }
    }
    class Test
    {
        static void Main(string[] args)
        {
            ConstructorOverloading obj1 = new ConstructorOverloading(10);
            obj1.Display();
            ConstructorOverloading obj2 = new ConstructorOverloading(10, 20);
            obj2.Display();
            ConstructorOverloading obj3 = new ConstructorOverloading(10, 20, 30);
            obj3.Display();
            Console.ReadKey();
        }
    }
}
Wyjście:

Przykład przeciążania metody w czasie rzeczywistym przy użyciu języka C#:

Załóżmy, że pracujesz nad projektem w czasie rzeczywistym. Jedną z obowiązkowych rzeczy, które musimy zrobić, jest rejestrowanie. Za każdym razem, gdy pojawia się żądanie, gdy wywołanie metody musimy przechwycić szczegóły żądania, musimy zarejestrować niezbędne informacje w pliku tekstowym lub w bazie danych. Nawet jeśli wystąpiły jakieś wyjątki, musimy również zarejestrować szczegóły wyjątku, aby później móc zweryfikować dziennik i zidentyfikować przyczyny wyjątku. W poniższym przykładzie tworzymy klasę o nazwie Logger z wieloma przeciążonymi wersjami metody Log. Tak więc, zgodnie z naszymi wymaganiami, możemy wywołać odpowiednią metodę.

using System;
namespace MethodOverloading
{
    public class Logger
    {
        public static void Log(string ClassName, string MethodName, string Message)
        {
            Console.WriteLine($"DateTime: {DateTime.Now.ToString()}, ClassName: {ClassName}, MethodName:{MethodName}, Message:{Message}");
        }
        public static void Log(string uniqueId, string ClassName, string MethodName, string Message)
        {
            Console.WriteLine($"DateTime: {DateTime.Now.ToString()}, UniqueId: {uniqueId}, ClassName: {ClassName}, MethodName:{MethodName}, Message:{Message}");
        }
        public static void Log(string Message)
        {
            Console.WriteLine($"DateTime: {DateTime.Now.ToString()}, Message: {Message}");
        }
        public static void Log(string ClassName, string MethodName, Exception ex)
        {
            Console.WriteLine($"DateTime: {DateTime.Now.ToString()}, ClassName: {ClassName}, MethodName:{MethodName}, Exception Message:{ex.Message}, \nException StackTrace: {ex.StackTrace}");
        }

        //You create many overloaded versions as per your business requirements
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            string ClassName = "Program";
            string MethodName = "Main";
            string UniqueId = Guid.NewGuid().ToString();
            Logger.Log(ClassName, MethodName, "Message 1");
            Logger.Log(UniqueId, ClassName, MethodName, "Message 2");
            Logger.Log("Message 3");

            try
            {
                int Num1 = 10, Num2 = 0;
                int result = Num1 / Num2;
                Logger.Log(UniqueId, ClassName, MethodName, "Message 4");
            }
            catch(Exception ex)
            {
                Logger.Log(ClassName, MethodName, ex);
            }
            
            Console.ReadKey();
        }
    }
}
Wyjście:

W następnym artykule omówię Przeciążanie operatorów w C# z przykładami. Tutaj, w tym artykule, staram się wyjaśnić, czym dokładnie jest Method Overloading w C# oraz kiedy i jak używać Przeciążanie metody w C# z przykładami. Mam nadzieję, że spodoba ci się ten artykuł o przeciążaniu metod w C# z przykładami.