system.object Class in C#: जैसाकि हमने पहले भी Discuss किया था कि .NET Framework की सभी Classes वास्तव में System.Object Class की Derived Class ही होती हैं। इसलिए C# में हम जो भी Class Create करते हैं, हर वह Class वास्तव में Internally System.Object Class की Derived Class होती है, जिसे C# में object Keyword द्वारा Shorthand Notation के रूप में Represent किया जाता है।
हर Base Class की तरह ही System.Object Class में भी कुछ Members Define किए गए है, जो किसी भी अन्य .NET Class की तरह हमारे द्वारा Create की जाने वाली प्रत्येक Class में भी Directly Use करने के लिए Available होते हैं। इनमें से कुछ Methods को virtual Keyword के साथ Define किया गया है, जिन्हें Derived Class में Override किया जा सकता है, जबकि कुछ को static Modifier के साथ Define किया गया है।
System.Object Class में Define किए गए विभिन्न Members की Detailed जानकारी प्राप्त करने के लिए हम Visual Studio के Object Browser Feature को Use कर सकते हैं। जबकि सरल तरीके से समझें, तो System.Object Class को .NET Framework में कुछ निम्नानुसार Define किया गया है:
public class Object { // Virtual members. public virtual bool Equals(object obj); protected virtual void Finalize(); public virtual int GetHashCode(); public virtual string ToString(); // Instance-level, nonvirtual members. public Type GetType(); protected object MemberwiseClone(); // Static members. public static bool Equals(object objA, object objB); public static bool ReferenceEquals(object objA, object objB); }
Equals() Method
Default रूप से ये Method केवल उसी स्थिति में true Return करता है, जब Compare होने वाले दोनों Items समान Memory Location को Refer कर रहे होते हैं। अत: Equals() Method का प्रयोग दो Objects के Reference को Compare करने के लिए किया जाता है, न कि दो Object के Actual Data Members को Compare करने के लिए।
इसलिए सामान्यत: इस Method को Defied Class में इस की जानकारी प्राप्त करने के लिए Override किया जाता है, कि Compare होने वाले दोनों Derived Class Objects के Data Exactly समान हैं या नहीं।
जब हम Equals() Method को Override करते हैं, तब हमें इस बात का ध्यान रखना जरूरी होता है कि हम GetHashCode() Method का प्रयोग Container के Sub-Object को Retrieve करने के लिए Internally Hashtable Type द्वारा किया जाता है।
साथ ही सभी ValueType Classes सभी Structures के लिए इस Method को Override करते हैं। इसलिए ये केवल Value Based Comparisons के लिए ही उपयोगी होते हैं, Reference Based Comparisons के लिए नहीं।
Finalize() Method
जब इस Method को Call किया जाता है तो ये Method जिस Object के साथ Call किया जाता है, उस Object की Memory Release हो जाती है और वह Object Destroy हो जाता है।
GetHashCode() Method
ये Method एक Integer Value Return करता है, जो कि किसी Specific Object Instance का Unique Identifier होता है।
ToString() Method
ये Method किसी Object के String Representation को Return करता है, जबकि String Representation Return करने के लिए ये Method <namespace>.<type Name> Format Use करते हुए Fully Qualified नाम Use करता है।
इस Method को Sub-Class द्वारा अक्सर Override किया जाता है, ताकि Object के Fields को Name/Value Pair के रूप में String Format में Tokenized करके Return किया जा सके। जब हम इस Method को Use करते हैं, तब हमें Fully Qualified Name Use करने की जरूरत नहीं होती, बल्कि हम Name/Value Pair के माध्यम से ही Object की Internal State का पता लगा लेते हैं।
GetType() Method
ये Method हम जिस Object के साथ Use करते हैं, उस Object का Runtime Type Return करता है। ये Method सभी Objects के साथ Available होता है, जिसकी वजह से हम किसी भी Type के Object के साथ इसे Use करके उसके Type का पता लगा सकते हैं।
MemberwiseClone() Method
ये Method किसी Object की Member by Member Copy करता है, जिसकी वजह से एक बिल्कुल नया Object Create हो जाता है, जिसमें उसी Object सारे Data होते हैं, जिसके साथ इस Method को Use किया जाता है।
इस तरह से ये जो Methods हमें System.Object Class द्वारा प्राप्त होते हैं, ये सारे Methods हमारे द्वारा Create की जाने वाली हर Class में Exist होते हैं, जिन्हें हम हमारी जरूरत के अनुसार या तो Override कर सकते हैं या फिर Use कर सकते हैं। जैसे:
File Name: System.ObjectClassMethodsUsing.cs using System; namespace CSharpInterface { class MyData { private double D1; private double D2; private double D3; public MyData() { } public MyData(double d1, double d2, double d3) { D1 = d1; D2 = d2; D3 = d3; } public double Sum() { return D1 + D2 + D3; } } class Program { static void Main(string[] args) { MyData p1 = new MyData(); Console.WriteLine("ToString: {0}", p1.ToString()); Console.WriteLine("Hash code: {0}", p1.GetHashCode()); Console.WriteLine("Type: {0}", p1.GetType()); MyData p2 = p1; object o = p2; // Are the references pointing to the same object in memory? if (o.Equals(p1) && p2.Equals(o)) { Console.WriteLine("Same instance!"); } Console.ReadLine(); } } } // Output: ToString: CSharpClass.MyData Hash code: 46104728 Type: CSharpClass.MyData Same instance!
इस Program में हमने ToString(), GetHashCode() व GetType() नाम के तीन Methods को Use किया है, जबकि इन Methods को हमने हमारी MyData Class में Define नहीं किया है, फिर भी हम इन्हें Use कर पा रहे हैं, क्योंकि .NET Framework की हर Class System.Object Class की Derived Class ही है और हर Derived Classes System.Object Class में Defined इन Methods को Directly अथवा Override करके Use कर सकता है।
Overriding System.Object.ToString() Method
हम सामान्यत: जो भी Classes Create करते हैं, उन्हें सी/ो ही Console.WriteLine() Method में Pass करके उनके Data को Display नहीं कर सकते, क्योंकि Console.WriteLine() Method केवल String Data को ही Directly Display कर सकता है।
लेकिन यदि हम हमारी Class में ToString() Method को Override कर दें, तो हम बडी ही आसानी से अपने User Defined Type के Object को सी/ो ही Console.WriteLine() Method में Specify करके उसके Standard Data को Display कर सकते हैं।
हालांकि हम इस Method को किसी भी तरह से Override कर सकते हैं, लेकिन फिर भी Recommended Approach ये होता है कि हम अपने Type के Members के नाम व उनकी Values को Name/Value Pair के रूप में Specify करते हुए ToString() Method को Override करें, ताकि जब हम हमारी Class के Object को Console.WriteLine() Method में Specify करें, तो ये Method ToString() Method को Execute करके हमारे User Defined Type के Data को व्यवस्थित तरीके से Display कर सके।
उदाहरण के लिए यदि हम हमारी Watch Class के लिए इस Method को Override करना चाहें, तो हमारा Overridden Method कुछ निम्नानुसार हो सकता है
File Name: ToStringOverriddenWithWatchClass.cs using System; namespace CSharpInterface { class Watch { public byte hour { set; get; } public byte minute { set; get; } public Watch() { hour = 12; minute = 0; } public void SetTime(byte h, byte m) { hour = h; minute = m; } public override string ToString() { string time; time = string.Format("{0}:{1}", hour, minute); return time; } } class UsingWatchConstructor { static void Main(String[] arg) { Watch hmt = new Watch(); Console.Write("Time of the HMT Watch is: {0}\n", hmt.ToString()); Watch sonata = new Watch(); sonata.SetTime(10, 12); Console.Write("Time of the Sonata Watch is: {0}\n", sonata.ToString()); } } } // Output: Time of the HMT Watch is: 12:0 Time of the Sonata Watch is: 10:12
जब पिछली बार हमने ये Program बनाया था, तब हमने hmt व sonata Object के Time को Display करने के लिए DisplayTime() नाम का एक Method बनाया था, जबकि इस बार हमने DisplayTime() नाम का Method नहीं बनाया है, फिर भी हम Time को Normal तरीके से Console.WriteLine() Method द्वारा निम्नानुसार Display कर पा रहे हैं:
Console.Write(“Time of the HMT Watch is: {0}\n”, hmt.ToString());
Console.Write(“Time of the Sonata Watch is: {0}\n”, sonata.ToString());
क्योंकि इस बार हमने हमारी Watch Class में ToString() Method को निम्नानुसार तरीके से Override कर लिया है:
public override string ToString() { string time; time = string.Format("{0}:{1}", hour, minute); return time; }
परिणामस्वरूप जब Console.Write() Method में hmt या sonata के Time को Display करना होता है, तो हम इन Objects के साथ ToString() Method को Call कर लेते हैं। जिसकी वजह से उपरोक्त Overridden Method Execute होता है और hour व minute के आधार पर उपयुक्त Time को एक String Object के रूप में Return करता है, जिसे Console.Write() Method आसानी से Process करके हमें Watch Type के Objects hmt व sonata का Time Display कर देता है।
Overriding System.Object.Equals() Method
चूंकि Equals() Method केवल दो Objects के References को ही Equality के लिए Compare करता है न कि Value के लिए। यानी Equals() Method का प्रयोग करके हम इस बात का पता लगा सकते हैं कि दो Reference Variables समान Heap Area Data को Refer कर रहे हैं या नहीं।
लेकिन यदि हम इस बात का पता लगाना चाहें, कि समान Class के दो एकदम अलग Objects में सभी Data Members में समान Value Stored है या नहीं, तो इस जरूरत को पूरा करने के लिए जिस तरह से हमने ToString() Method को Override किया है, उसी तरह से हम Equals() Method को भी Override कर सकते हैं।
उदाहरण के लिए यदि हम हमारे Watch Class के Object को इस बात के लिए Check करना चाहें, कि hmt व sonata दोनों Objects में समान Time Stored है या नहीं, तो इस बात को Test करने के लिए हम Equals() Method को निम्न Program के अनुसार Override कर सकते हैं:
File Name: EqualsOverriddenWithWatchClass.cs using System; namespace CSharpInterface { class Watch { public byte hour { set; get; } public byte minute { set; get; } public Watch() { hour = 12; minute = 0; } public Watch(byte h, byte m) { hour = h; minute = m; } public void DisplayTime() { Console.WriteLine(hour + ":" + minute); } public override string ToString() { string time; time = string.Format("{0}:{1}", hour, minute); return time; } public override bool Equals(Object x) { if (x is Watch && x != null) { Watch temp = (Watch)x; if (this.hour == temp.hour && this.minute == temp.minute) return true; else return false; } return false; } } class UsingWatchConstructor { static void Main(String[] arg) { Watch hmt = new Watch(10, 12); Watch sonata = new Watch(10, 12); Console.Write("Both Watch have Same Time: {0}\n", hmt.Equals(sonata)); } } } // Output: EqualsOverriddenWithWatchClass.cs(4,9): warning CS0659: 'CSharpClass.Watch' overrides Object.Equals(object o) but does not override Object.GetHashCode() Both Watch have Same Time: True
इस Program में हमने Equals() Method को कुछ निम्नानुसार Override किया है, ताकि हम Watch Class के दो Objects के इस बात के लिए Check कर सकें, कि दोनों का Time एक समान है या नहीं:
public override bool Equals(object x) { if (x is Watch && x != null) { Watch temp = (Watch)x; if (this.hour == temp.hour && this.minute == temp.minute) return true; else return false; } return false; }
चूंकि Equals() Method Parameter के रूप में एक object Type के Object को Accept करता है। इसलिए सबसे पहले हमने उपरोक्त Code में इसी बात को Check किया है कि Parameter के रूप में आने वाला Object Watch Type का है या नहीं। साथ ही इस बात को भी Check किया है कि Watch Type का Object होने के बावजूद आने वाले Object में null तो Store नहीं है।
यदि Parameter के रूप में आने वाला Object Watch Type का न हो या आने वाले Parameter में null हो, तो ये Overridden Method False Return कर देता है, जो इसी बात का Indication है कि Compare होने वाले दोनों Watch Object का Time एक समान नहीं है।
लेकिन यदि Parameter के रूप में आने वाले Object में null न हो और Object Watch Type का हो, तो if Condition true होने की स्थिति में C# Compiler if Statement Block में Enter करता है, जहां सबसे पहले Parameter के रूप में आने वाले Object की Casting करके उसका Reference, Watch Type के Object में Store किया जाता है और फिर एक और if Statement द्वारा दोनों Objects के सभी Members को One by One Equal Value के लिए Compare किया है।
परिणामस्वरूप यदि दोनों Objects के सभी Members में समान Data हों, तो ये Overridden Method true Return करता है अन्यथा False Return करता है।
इस तरह से हम Equals() Method को किसी भी Class में Override करके उपरोक्तानुसार Object की Values को Member-Wise Compare करवाते हुए Equality के लिए Test कर सकते हैं।
हालांकि हम इस तरीके को Use करके दो Objects को Data-Wise Equality के लिए Compare कर सकते हैं। लेकिन इस तरीके को किसी ऐसे Structure या Class के साथ Use करना काफी असुविधाजनक हो सकता है, जिसमें बहुत सारे Data Members हों।
इसलिए सामान्यत: यदि Class में ToString() Method को Implement किया गया होता है, तो हम ToString() Method द्वारा ही Equality Comparision को भी Perform कर सकते हैं। क्योंकि ToString() Method में सामान्यत: Class के सभी Data Members को Name/Value Pair के रूप में Specify किया जाता है, जिसका फायदा उठाते हुए हम Repeat Code लिखने से बच सकते हैं।
चूंकि हमने हमारी Watch Class में ToString() Method को Override किया है। इसलिए इस Method को Use करते हुए हम Equals() Method को निम्नानुसार Modify कर सकते हैं:
public override bool Equals(object x) { return x.ToString() == this.ToString(); }
जैसाकि हम समझ सकते हैं कि इस Modified Equals() Method में हमने Parameter के रूप में आने वाले Object के Type को इस बात के लिए Compare नहीं किया है कि आने वाला Object Watch Type का है या नहीं अथवा उसमें null Stored है या नहीं। फिर भी हमारा Program Normal तरीके से Run हो रहा है। क्योंकि .NET में ToString() Method सभी प्रकार के Objects के साथ समान रूप से काम करने के लिए Design किया गया है।
System.Object.GetHashCode() Method
जैसाकि पिछले Program के Output में हम देख सकते हैं कि हालांकि हमारा Program हमें उपयुक्त Output दे रहा है, फिर भी एक Warning Show हो रहा है। ये Warning इस लिए Show हो रहा है, क्योंकि जब हम Equals() Method को Override करते हैं, तो C# Compiler GetHashCode() Method को भी Override करने के लिए Instruct करता है।
Hash Code एक Numerical Value होता है जो किसी Object की Particular State को Represent करता है। उदाहरण के लिए यदि हम दो String Variable Create करते हैं और दोनों ही String Objects में “Hello! World” String Store करते हैं, तो दोनों ही String Objects के लिए हमें समान Hash Code प्राप्त होता है।
लेकिन यदि हम दोनों में से किसी एक Object में Value के रूप में “hello! World” String Specify कर दें, तो दोनों Objects का Hash Code बदल जाता है, क्योंकि दोनों Objects में अब एक समान Data Stored नहीं हैं।
Default रूप से System.Object.GetHashCode() Method हमारे Object की Memory की Current Location से Hash Code प्राप्त करता है। लेकिन यदि हम Custom Type Define करते हैं, जिसे हम System.Collections Namespace के Hashtable Type में Store करना चाहते हैं, तो उस स्थिति में हमें हमेंशा इस Method को Override करना जरूरी होता है। क्योंकि Hashtable Type Internally Equals() व GetHashCode() Methods को Use करके ही Correct Object Retrieve करता है।
यानी System.Collections.Hashtable Class, Internally GetHashCode() Method को Call करके इस बात का पता लगाता है कि Required Object Memory में किस Location पर स्थित है, जबकि GetHashCode() Method Internally Equals() Method को Call करके Exact Matching Object को Identify करता है।
हालांकि हम हमारी Watch Class को System.Collections.Hashtable में Store नहीं कर रहे हैं, फिर भी हम GetHashCode() को Override कर रहे हैं, ताकि हम इस बात को समझ सकें कि इस Method को किस तरह से Override किया जाता है।
Hash Code Create करने के लिए कई Algorithms Available हैं। लेकिन हम सामान्यत: System.String के GetHashCode() Implementation के आधार पर ही Hash Code Create करते हैं, जो कि काफी आसान होता है।
Sting Class में पहले से ही काफी अच्छा Hash Code Algorithm Exist है, जो कि String के Character Data के आधार पर Hash Value Generate करता है, इसलिए यदि हम किसी Class के Field Data को Identify करना चाहते हैं, जो कि इसके सभी Instances या Objects के लिए Unique हो, तो हमें केवल Field के नाम के साथ GetHashCode() Method को ही Call करना होता है। जैसे:
class Watch { public byte hour { set; get; } public byte minute { set; get; } public override int GetHashCode() { return hour.GetHashCode(); } . . . }
तो ये Overridden GetHashCode() Method हमारी Watch Class के हर Instance के लिए एक Unique Hash Code Generate कर लेता है। जबकि यदि हमने ToString() Method को Override किया हो, तो हम हमारे ToString() Method को निम्नानुसार तरीके से Use करते हुए भी इस Method को Unique Hash Code के लिए Override कर सकते हैं:
class Watch { public byte hour { set; get; } public byte minute { set; get; } public override int GetHashCode() { return this.ToString().GetHashCode(); } public override string ToString() { string time; time = string.Format("{0}:{1}", hour, minute); return time; } . . . }
Equals() Method के अलावा System.Object Class में System.Object.Equals() नाम का एक Static Method भी Define किया गया है, जिसका प्रयोग करके हम किसी Class के दो Objects को Data Members की Equality के लिए Use कर सकते हैं। यानी जो काम हमने Equals() Method को Override करके किया था, उसी काम को हम object.Eqauls() Static Method द्वारा भी कर सकते हैं। जैसे:
File Name: object.EqualsStaticMethodWithWatchClass.cs using System; namespace CSharpInterface { class Watch { public byte hour { set; get; } public byte minute { set; get; } public Watch() { hour = 12; minute = 0; } public Watch(byte h, byte m) { hour = h; minute = m; } public void DisplayTime() { Console.WriteLine(hour + ":" + minute); } } class UsingWatch { static void Main(String[] arg) { Watch hmt = new Watch(10, 12); Watch sonata = new Watch(10, 10); Watch sameHMT = hmt; Console.Write("Both Watch have Same Time: {0}\n", object.Equals(hmt, sonata)); Console.Write("Both References Pointing Same Object: {0}\n", object.ReferenceEquals(hmt, sameHMT)); } } } // Output: Both Watch have Same Time: False Both References Pointing Same Object: True
जैसाकि इस Program द्वारा हमम समझ सकते हैं कि object.Equals() Static Method का प्रयोग करके हम दो Object को Data-Wize Equality के लिए Test कर सकते हैं। जबकि object.ReferenceEquals() Static Method का प्रयोग करके हम दो Object को Reference-Wize Equality के लिए Test कर सकते हैं।
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook C#.NET in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
C#.NET in Hindi | Page:908 | Format: PDF