Operator Overloading in C#.NET

Unary Operator Overloading in C#.NET

जब हम Unary Operators को Overload करना चाहते हैं, तब हमें operator x() Overloading Method में केवल एक ही Parameter Pass करना होता है। उदाहरण के लिए यदि हम हमारे पिछले Program में ही Decrement (––) Operator को Overload करना चाहें, तो हमें निम्न Program में बताए अनुसार इस Operator को Single Parameter के माध्‍यम से Overload करना होगा:

File Name: DecrementOperatorOverloading.cs
using System;

namespace CSharpClass
{
    class Coordinate
    {
        int x { get; set; }
        int y { get; set; }

        public Coordinate() { }
        public Coordinate(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public void Position(string type)
        {
            Console.WriteLine("{0} Position: {1},{2}", type, x, y);
        }

        public static Coordinate operator +(Coordinate operand1, Coordinate operand2)
        {
            Coordinate temp = new Coordinate();
            temp.x = operand1.x + operand2.x;
            temp.y = operand1.y + operand2.y;
            return temp;
        }

        public static Coordinate operator --(Coordinate operand)
        {
            Coordinate temp = new Coordinate();
            temp.x = --operand.x;
            temp.y = --operand.y;
            return temp;
        }
    }

    class OperatorOverloadingBasic
    {
        static void Main()
        {
            Coordinate pixel = new Coordinate(12, 21);
            pixel.Position("Before Decrement Pixel is Positioned at: ");

            pixel--;
            pixel.Position("After Decrement Pixel is Positioned at: ");
        }
    }
}

Output:
	Actual Pixel Position: 11,20

इस Program के Output व Overloaded Decrement Operator की Working के आधार पर आसानी से समझ सकते हैं कि किस तरह से अपनी जरूरत के अनुसार किसी Unary Operator को किसी Custom Type के लिए Overload किया जा सकता है।

Overloading operator x() Method

जिस तरह से हम किसी अन्‍य Method को Overload करते हैं, उसी तरह से हम हमारे Custom Type के लिए किसी Particular Operator की Overloading करने वाले operator x() Method को अलग-अलग तरह के Operations Perform करने के लिए Overload कर सकते हैं।

उदाहरण के लिए पिछले Program में हमने दो Coordinate Type के Objects को आपस में Add करने के लिए “+” Operator को Overload किया था। हम इसी Program को निम्नानुसार तरीके से Modify कर सकते हैं, जो operator x() Method की Overloading के Concept को आसानी से समझने में मदद करेगा:

 File Name: opeator+()MethodOperatorOverloading.cs
using System;

namespace CSharpClass
{
    class Coordinate
    {
        int x { get; set; }
        int y { get; set; }

        public Coordinate() { }
        public Coordinate(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public void Position(string type)
        {
            Console.WriteLine("{0} Position: {1},{2}", type, x, y);
        }

        public static Coordinate operator +(Coordinate operand1, Coordinate operand2)
        {
            Coordinate temp = new Coordinate();
            temp.x = operand1.x + operand2.x;
            temp.y = operand1.y + operand2.y;
            return temp;
        }

        public static Coordinate operator +(Coordinate operand1, int operand2)
        {
            Coordinate temp = new Coordinate();
            temp.x = operand1.x + operand2;
            temp.y = operand1.y + operand2;
            return temp;
        }

        public static Coordinate operator --(Coordinate operand)
        {
            Coordinate temp = new Coordinate();
            temp.x = --operand.x;
            temp.y = --operand.y;
            return temp;
        }
    }

    class OperatorOverloadingBasic
    {
        static void Main()
        {
            Coordinate pixel1 = new Coordinate(12, 21);
            Coordinate pixel2 = new Coordinate(10, 50);
            pixel1.Position("Before Adding pixel1 with pixel2, pixel1 is Positioned at: ");

            pixel1 += pixel2;
            pixel1.Position("After Adding pixel1 with pixel2, pixel1 is Positioned at: ");

            pixel1 += 10;
            pixel1.Position("After Adding Integer 10 with pixel1, pixel1 is Positioned at: ");
        }
    }
}

// Output:
	Before Adding pixel1 with pixel2, pixel1 is Positioned at:  Position: 12,21
After Adding pixel1 with pixel2, pixel1 is Positioned at:  Position: 22,71
	After Adding Integer 10 with pixel1, pixel1 is Positioned at:  Position: 32,81

इस Program में हमने “+” Operator को निम्नानुसार Prototype द्वारा दो बार Overload किया है:

public static Coordinate operator +(Coordinate operand1, Coordinate operand2)
. . .
public static Coordinate operator +(Coordinate operand1, int operand2)
. . .

परिणामस्वरूप जब हम निम्नानुसार Statement Execute होता है:

pixel1 += pixel2;

जहां “+=” Operator के दोनों और Coordinate Type का Object होता है, तो पहला वाला operator +() Method Execute होता है। लेकिन जब निम्नानुसार Statement Execute होता है:

pixel1 += 10;

जहां “+=” Operator के Right Side में कोई Coordinate Type का Object नहीं बल्कि Integer Type Value होती है, तो दूसरा वाला operator +() Method Execute होता है और हमें उपरोक्त Program के अनुसार Output प्राप्त होता है।

Comparision Operator Overloading in C#.NET

जब हम Comparision Operators की Overloading करना चाहते हैं, तब हमें हमेंशा एक Boolean Value true या false Return करना होता है क्योंकि Comparision Operators का प्रयोग हमेंशा Comparision करने के लिए किया जाता है और Comparision के बाद हमेंशा true या false मान ही Return होता है, जो Comparision के Successful या Fail होने को Indicate करता है।

File Name: ComparisionOperatorOverloading.cs
using System;

namespace CSharpClass
{
    class Time
    {
        byte hour { get; set; }
        byte minute { get; set; }

        public Time() { }
        public Time(byte h, byte m)
        {
            this.hour = h;
            this.minute = m;
        }

        public static bool operator <(Time operand1, Time operand2)
        {
            int totalMinutes1 = operand1.hour * 60 + operand1.minute;
            int totalMinutes2 = operand2.hour * 60 + operand2.minute;

            if (totalMinutes1 < totalMinutes2)
                return true;
            else
                return false;
        }

        public static bool operator >(Time operand1, Time operand2)
        {
            int totalMinutes1 = operand1.hour * 60 + operand1.minute;
            int totalMinutes2 = operand2.hour * 60 + operand2.minute;

            if (totalMinutes1 > totalMinutes2)
                return true;
            else
                return false;
        }
    }

    class OperatorOverloading
    {
        static void Main()
        {
            Time hmt = new Time(12, 10);
            Time sonata = new Time(23, 30);

            if (hmt < sonata)
                Console.WriteLine("Time of SONATA is Greater then HMT");
            else
                Console.WriteLine("Time of HMT is Greater then SONATA");
        }
    }
}

// Output:
	Time of SONATA is Greater then HMT

इस Program में हमने एक Time को दूसरे Time से Compare करवाने के लिए “<” व “>” Operators को Overload किया है। C# में यदि हम “<” Operator को Overload करते हैं, तो हमें “>” Operator को भी Overload करना Compulsory होता है। इसी तरह से यदि हम “<=” Operator को Overload करते हैं, तो हमें “>=” Operator को भी Overload करना Compulsory होता है।

Equality Operator Overloading in C#.NET

जब हम == या != Operators को किसी Custom Type के लिए Overload करना चाहते हैं, तब हमें थोडा अलग Process Use करना पडता है। क्योंकि Objects हमेंशा Heap Area में Store होते हैं, जिनका Reference Stack में Store होता है।

इसलिए यदि हम दो Objects को Equality के लिए Compare करते हैं, तो हमें इस बात को तय करना जरूरी होता है कि हम दोनों Objects के Heap Area में Stored Actual Data को Compare कर रहे हैं या केवल उनके References को Compare कर रहे हैं।

यदि हम केवल References को इस बात के लिए Compare करना चाहते हैं कि दोनों Stack Variables समान Heap Area को Refer कर रहे हैं या नहीं, तो हमें कुछ Special करने की जरूरत नहीं होती।

लेकिन सामान्‍यत: हम दो Custom Type Objects के Data को Equality के लिए Compare करने हेतु ही Equality Operators को Overload करते हैं। इसलिए इस स्थिति में हमें .NET Framework के System.Object.Equals() Method को Override करना पडता है, क्योंकि यही Method दो Objects को उनके Data की Equality के लिए Compare करता है।

साथ ही जब हम System.Object.Equals() Method को Override करते हैं, तो हमें System.Object.GetHashCode() Method को भी Override करना जरूरी होता है। Overriding के बारे में हम Inheritance व Polymorphism Chapter के अन्तर्गत समझेंगे। इसलिए Equality Operator की Overloading के लिए यहां हम जो Program Create करेंगे, वह सम्भवतया अभी समझ में नहीं आ,गा।

फिर भी Equality Operator की Overloading करने के लिए हमें निम्नानुसार Program की तरह System.Object.Equals() Method व System.Object.GetHashCode() Method को Override करते हुए == != दोनों Operators को Overload करना होगा क्योंकि C# हमें दोनों में से सिर्फ किसी एक Operator को Overload नहीं करने देता:

File Name: EqualityOperatorOverloading.cs
using System;

namespace CSharpClass
{
    class Time
    {
        byte hour { get; set; }
        byte minute { get; set; }

        public Time() { }
        public Time(byte h, byte m)
        {
            this.hour = h;
            this.minute = m;
        }

        public override bool Equals(object arg)
        {
            return arg.ToString() == this.ToString();
        }

        public override int GetHashCode()
        {
            return this.ToString().GetHashCode();
        }

        public static bool operator ==(Time operand1, Time operand2)
        {
            return operand1.Equals(operand2);
        }

        public static bool operator !=(Time operand1, Time operand2)
        {
            return !operand1.Equals(operand2);
        }
    }

    class EqualityOperatorOverloading
    {
        static void Main()
        {
            Time hmt = new Time(12, 10);
            Time sonata = new Time(12, 10);
            Time titan = new Time(10, 20);

            Console.WriteLine("HTML == SONATA: {0}", hmt == sonata);
            Console.WriteLine("HTML != SONATA: {0}\n", hmt != sonata);

            Console.WriteLine("HTML == TITAN: {0}", hmt == titan);
            Console.WriteLine("HTML != TITAN: {0}", hmt != titan);

        }
    }
}

// Output:
   HTML == SONATA: True
   HTML != SONATA: False

   HTML == TITAN: True
   HTML != TITAN: False

true and false Operator Overloading in C#.NET

truefalse Operators को हम Unary Operators की तरह Use करने के लिए Overload कर सकते हैं। इन Operators के Overloaded Versions का प्रयोग Custom Types के Objects से true या false मान को Return करने के लिए किया जा सकता है, ताकि इन्हें if, while, for, Conditional Operator आदि में Use किया जा सके।

truefalse Operators को भी Pair के रूप में ही Overload करना जरूरी होता है। यानी हम किसी Custom Type के लिए इन दोनों में से केवल किसी एक को Overload नहीं कर सकते। यदि हम हमारे Coordinate Type के लिए इन Operators को Overload करना चाहें, तो निम्नानुसार Program के अनुसार ऐसा कर सकते हैं:

File Name: true-false-OperatorOverloading.cs
using System;

namespace CSharpClass
{
    class Coordinate
    {
        int x { get; set; }
        int y { get; set; }

        public Coordinate() { }
        public Coordinate(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public static bool operator true(Coordinate operand)
        {
            if (operand.x != 0 && operand.y != 0)
                return true;
            else
                return false;
        }

        public static bool operator false(Coordinate operand)
        {
            if (operand.x == 0 && operand.y == 0)
                return true;
            else
                return false;
        }
    }

    class OperatorOverloadingBasic
    {
        static void Main()
        {
            Coordinate pixel1 = new Coordinate(12, 21);
            Coordinate pixel2 = new Coordinate(0, 0);

            if (pixel1)
                Console.WriteLine("Coordinate is not 0,0 of pixel1");
            else
                Console.WriteLine("Coordinate is 0,0 of pixel1");

            if (pixel2)
                Console.WriteLine("Coordinate is not 0,0 of pixel2");
            else
                Console.WriteLine("Coordinate is 0,0 of pixel2");
        }
    }
}

// Output:
	Coordinate is not 0,0 of pixel1
	Coordinate is 0,0 of pixel2

जैसाकि उपरोक्त Program द्वारा हम समझ सकते हैं कि जब हम किसी Custom Type में truefalse Operators को निम्नानुसार तरीके से Overload करते हैं:

        public static bool operator true(Coordinate operand)
        {
            if (operand.x != 0 && operand.y != 0)
                return true;
            else
                return false;
        }

        public static bool operator false(Coordinate operand)
        {
            if (operand.x == 0 && operand.y == 0)
                return true;
            else
                return false;
        }

तो फिर हम हमारे Class Type को निम्नानुसार तरीके से if Statement में Use कर सकते हैं:

if (pixel1)
. . .
if (pixel2)
. . .

इसी तरह से हम हमारे Coordinate Type के Object को अपने Program में हर उस स्थान पर Use कर सकते हैं, जहां Object को true/false मान के लिए Compare करना होता है।

जिस तरह से हमने इन विभिन्न प्रकार के UnaryBinary Operators को Overload किया है, उसी तरह से हम Logical, Short-Circuit आदि अन्‍य Operators को भी अपनी जरूरत के अनुसार Overload कर सकते हैं।

Conversion Operator Overloading in C#.NET

जब हम विभिन्न प्रकार की जरूरतों को पूरा करने के लिए अपने Custom Type में विभिन्न प्रकार के Operators को Overload करते हैं, तो कई बार हमें ऐसी जरूरत पडती है कि हमें हमारे Custom Type को किसी अन्‍य Custom Type या Built-In Type के साथ Use करना होता है।

चूंकि C# एक Strict Type को Support करने वाली Programming Language है, इसलिए हम किसी एक Type को किसी दूसरे Type में Normal तरीके से Assign या Initialize नहीं कर सकते और यदि हम ऐसा करने की कोशिश करते हैं, तो C# हमें Compile Time Error Return करता है। इस प्रकार की स्थिति को Handle करने के लिए भी C# हमें एक Special प्रकार का Operator Create करने की सुविधा देता है, जिसे Conversion Operator के नाम से जाना जाता है।

ये Conversion Operator किसी एक Type के Object को किसी दूसरे Type में Convert करने का काम करता है। इसलिए जब हम किसी Type के लिए Conversion Operator Create कर लेते हैं, तो फिर उस Operator को हम हमारे Program में कभी भी और कहीं भी उपयोग में ले सकते हैं। C# हमें Implicit व Explicit Operators के रूप में दो प्रकार के Conversion Operators Create करने की सुविधा देता है, जिनका General Syntax निम्नानुसार होता है:

	public static operator implicit target-type(source-type v)
	{ 
		return value; 
	}
	
	public static operator explicit target-type(source-type v) 
	{ 
		return value; 
	}

इस Syntax में source-type वह Type है, जिसे हम target-type में Convert करना चाहते हैं और value वह Value है, जो Class Conversion के बाद Generate होती है। Conversion Type हमेंशा target-type का Data Return करता है और इसके अलावा किसी भी अन्‍य Type के Data को Conversion Operator से Return नहीं किया जा सकता।

यदि हम Conversion Operator के साथ implicit Specify करते है, तो Conversion Operator उस समय Automatically Invoke हो जाता है, जब हम उस Type के Object को किसी Expression में Use करते हैं, जिसमें Conversion की जरूरत होती है। जबकि यदि हम Conversion Operator के साथ explicit Specify करते है, तो Conversion Operator उस समय Invoke होता है, जब हम Casting करते हैं।

हम किसी Class में इन दोनों तरह के Conversion Operators को समान Source Target के लिए एक साथ Specify नहीं कर सकते। इन दोनों ही Conversion Operators को हम निम्नानुसार तरीके से अपने अपनी Watch Class के साथ Apply कर सकते हैं:

File Name: ImplicitConversionOperator.cs	
using System;

namespace CSharpClass
{
    class Time
    {
        byte hour { get; set; }
        byte minute { get; set; }

        public Time() { }
        public Time(byte h, byte m)
        {
            this.hour = h;
            this.minute = m;
        }

        public static implicit operator string(Time operand)
        {
            return string.Format("{0}:{1}", operand.hour, operand.minute);
        }

        public static implicit operator int(Time operand)
        {
            return operand.hour * 60 + operand.minute;
        }
    }

    class OperatorOverloading
    {
        static void Main()
        {
            Time hmt = new Time(12, 10);
            Time sonata = new Time(23, 30);

            int mins = hmt;
            Console.WriteLine("Total Minutes: " + mins);

            string time = hmt;
            Console.WriteLine("Time: " + time);
        }
    }
}

// Output:
	Total Minutes: 730
	Time: 12:10

इस Program में हमने दो Implicit Conversion Operators Define किए हैं, जो Time Type को string Type व int Type में Convert करके Return करते हैं। इसलिए जब Main() Method में निम्न Statement Execute होता है:

int mins = hmt;

तो जैसाकि हम देख सकते हैं कि हम एक Time Type के Object को एक Integer Type के Variable में Initialize कर रहे हैं। हम ऐसा इसीलिए कर सकते हैं, क्योंकि जैसे ही उपरोक्त Statement Execute होता है, C# Internally Automatically निम्न Conversion Method को Invoke करता है:

        public static implicit operator int(Time operand)
        {
            return operand.hour * 60 + operand.minute;
        }

परिणामस्वरूप Time Type के Object का Time, Minutes में Convert होकर Return होता है, जिसे Output में Display कर दिया जाता है। फिर जब Main() Method में निम्न Statement Execute होता है:

string time = hmt;

तो C# Compiler इस Statement के लिए Automatically निम्न Conversion Operator Method Invoke करता है:

        public static implicit operator string(Time operand)
        {
            return string.Format("{0}:{1}", operand.hour, operand.minute);
        }

और Time Type के मान को String Format में Return कर देता है। परिणामस्वरूप हमे हमारे Time को Display करने के लिए Display() नाम का Method Create करने की जरूरत नहीं पडती।

जिस तरह से हमने इस Program में Implicit Conversion Operator Methods को Define किया है, उसी तरह हम Explicit Conversion Method भी Define कर सकते हैं। यदि हम हमारे इसी Program को Explicit Conversion Method के लिए Modify करना चाहें, तो हमारा Program कुछ निम्नानुसार बनेगा:

File Name: ExplicitConversionOperator.cs
using System;

namespace CSharpClass
{
    class Time
    {
        byte hour { get; set; }
        byte minute { get; set; }

        public Time() { }
        public Time(byte h, byte m)
        {
            this.hour = h;
            this.minute = m;
        }

        public static explicit operator string(Time operand)
        {
            return string.Format("{0}:{1}", operand.hour, operand.minute);
        }

        public static explicit operator int(Time operand)
        {
            return operand.hour * 60 + operand.minute;
        }
    }

    class OperatorOverloading
    {
        static void Main()
        {
            Time hmt = new Time(12, 10);

            int mins = (int)hmt;
            Console.WriteLine("Total Minutes: " + mins);

            string time = (string)hmt;
            Console.WriteLine("Time: " + time);
        }
    }
} 

// Output:
	Total Minutes: 730
	Time: 12:10

ये Program Exactly पिछले Program की तरह ही है और Exactly पिछले Program की तरह ही Output Return करता है। अन्तर केवल इतना है कि इस Program में हमने दोनों Conversion Operator Methods के साथ explicit Keyword का प्रयोग किया है, जिसकी वजह से C# Compiler उस समय Automatically Time Type के Object को int या string में Convert नहीं करताए जब Main() Method में निम्न Statements Specify किया जाता है:

int mins = hmt;
string time = hmt;

बल्कि यदि हम ये इस तरह का Statement Specify करें, तो C# Compiler Error Return करता है। इसलिए इस Program में यदि हम Time Type के Object को Integer या String Type के Variable में Store करना चाहते हैं, तो हमें निम्नानुसार Manual Type Casting करनी पडती है:

int mins = (int)hmt;
string time = (string)hmt;

इस तरह से हम विभिन्न प्रकार के Custom Type Conversion के लिए अपने स्वयं के Implicit या Explicit Conversion Operator Method Create कर सकते हैं और अपनी विभिन्न प्रकार की Problems को Solve करने के लिए वैसे ही Codes Define कर सकते हैं, जैसे .NET Framework की Classes में किया गया है।

Operator Overloading Restrictions

हालांकि हम C# में कई Operators को Overload कर सकते हैं, लेकिन सभी Operators को Overload नहीं कर सकते। जिन Operators को Overload किया जा सकता है, उन्हें इस Overloading Concepts Section की शु:आत में एक सारणी के रूप में Specify किया गया है।

जब हम Conversion Operator Method Define करते हैं, तो Source TypeTarget Type दोनों का Class या Structure Type होना जरूरी होता है। यानी हम किसी पहले से Defined Built-In Type जैसे कि int या double को Conversion Operator Method द्वारा Redefine नहीं कर सकते।

इसी तरह से हम किसी object से किसी अन्‍य Type को या किसी अन्‍य Type से object का Conversion नहीं कर सकते। साथ ही हम एक ही Class में समान Source Type Target Type के लिए Implicit Explicit दोनों Conversion Operator Methods को एक साथ Implement नहीं कर सकते।

इसी तरह से हम किसी Interface Type को अन्‍य Type में या अन्‍य Type को Interface Type में भी Convert नहीं कर सकते। न ही हम किसी Assignment Operator को Overload कर सकते हैं। क्योंकि जब हम किसी Binary Operator जैसे कि “+” या “-“ को Overload करते हैं, तो उसके साथ ही Automatically “==” व “-=” Assignment Operators Automatically Overload हो जाते हैं।

हमें उसी स्थिति में Implicit Conversion करना चाहिए जबकि Conversion करने से किसी भी तरह से Data का Loss न हो। यदि Implicit Conversion करने से Data का Loss (Truncation, Overflow, Loss of Sign, etc…) होना सम्भव हो या कोई Runtime Exception Generate हो सकता हो, तो उस स्थिति में हमें Explicit Conversion करने के लिए Explicit Conversion Operator Method को ही Define करना चाहिए।

Operator Overloading in C#
Pointers in C#

C# in Hindiये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook C#.NET in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

C#.NET in Hindi | Page:908 | Format: PDF

BUY NOW GET DEMO REVIEWS