खोज…


परिचय

कीवर्ड पूर्वनिर्धारित हैं, संकलक के विशेष अर्थ वाले आरक्षित पहचानकर्ता। वे @ उपसर्ग के बिना आपके प्रोग्राम में पहचानकर्ता के रूप में उपयोग नहीं किए जा सकते। उदाहरण के लिए @if एक कानूनी पहचानकर्ता है, लेकिन if नहीं तो कीवर्ड।

टिप्पणियों

C # में "कीवर्ड" (या आरक्षित शब्द) का एक पूर्वनिर्धारित संग्रह है, जिसमें से प्रत्येक का एक विशेष कार्य है। जब तक @ साथ उपसर्ग नहीं किया जाता है तब तक इन शब्दों को पहचानकर्ता (चर, विधियों, वर्गों, आदि के नाम) के रूप में उपयोग नहीं किया जा सकता है।

इनके अलावा, C # कुछ कीवर्ड का उपयोग कोड में विशिष्ट अर्थ प्रदान करने के लिए भी करता है। उन्हें प्रासंगिक कीवर्ड कहा जाता है। प्रासंगिक कीवर्ड का उपयोग पहचानकर्ता के रूप में किया जा सकता है और पहचानकर्ता के रूप में उपयोग किए जाने पर @ साथ उपसर्ग करने की आवश्यकता नहीं है।

stackalloc

stackalloc कीवर्ड स्टैक पर मेमोरी का एक क्षेत्र बनाता है और उस मेमोरी की शुरुआत में एक पॉइंटर लौटाता है। स्टैक आबंटित मेमोरी स्वचालित रूप से हटा दी जाती है जब इसे बनाया गया गुंजाइश बाहर निकलता है।

//Allocate 1024 bytes. This returns a pointer to the first byte.
byte* ptr = stackalloc byte[1024];

//Assign some values...
ptr[0] = 109;
ptr[1] = 13;
ptr[2] = 232;
...

एक असुरक्षित संदर्भ में उपयोग किया जाता है।

जैसा कि C # में सभी बिंदुओं के साथ होता है, रीड और असाइनमेंट की कोई सीमा नहीं होती है। आवंटित मेमोरी की सीमा से परे पढ़ने के अप्रत्याशित परिणाम होंगे - यह मेमोरी के भीतर कुछ मनमाने स्थान तक पहुँच सकता है या इसके कारण एक्सेस उल्लंघन अपवाद हो सकता है।

//Allocate 1 byte
byte* ptr = stackalloc byte[1];

//Unpredictable results...
ptr[10] = 1;
ptr[-1] = 2;

स्टैक आबंटित मेमोरी स्वचालित रूप से हटा दी जाती है जब इसे बनाया गया गुंजाइश बाहर निकलता है। इसका मतलब यह है कि आपको स्टैकलॉक के साथ बनाई गई मेमोरी को कभी भी वापस नहीं करना चाहिए या इसे जीवनकाल से परे स्टोर करना चाहिए।

unsafe IntPtr Leak() {
    //Allocate some memory on the stack
    var ptr = stackalloc byte[1024];

    //Return a pointer to that memory (this exits the scope of "Leak")
    return new IntPtr(ptr);
}

unsafe void Bad() {
     //ptr is now an invalid pointer, using it in any way will have
     //unpredictable results. This is exactly the same as accessing beyond
     //the bounds of the pointer.
     var ptr = Leak();
}

stackalloc उपयोग केवल तब किया जा सकता है जब चर घोषित और आरंभ करना। निम्नलिखित मान्य नहीं है:

byte* ptr;
...
ptr = stackalloc byte[1024];

टिप्पणियों:

stackalloc उपयोग केवल प्रदर्शन अनुकूलन (या तो गणना या stackalloc लिए) के लिए किया जाना चाहिए। यह इस तथ्य के कारण है कि:

  • कचरा संग्राहक की आवश्यकता नहीं है क्योंकि ढेर के बजाय मेमोरी को स्टैक पर आवंटित किया जाता है - जैसे ही चर दायरे में जाता है, मेमोरी जारी की जाती है
  • ढेर के बजाय स्टैक पर मेमोरी आवंटित करना तेज है
  • डेटा की स्थानीयता के कारण सीपीयू पर कैश हिट की संभावना बढ़ाएं

परिवर्तनशील

किसी फ़ील्ड में volatile कीवर्ड जोड़ना कंपाइलर को इंगित करता है कि फ़ील्ड का मान कई अलग-अलग थ्रेड द्वारा बदला जा सकता है। volatile कीवर्ड का प्राथमिक उद्देश्य कंपाइलर ऑप्टिमाइज़ेशन को रोकना है जो केवल एकल-थ्रेडेड एक्सेस को ग्रहण करता है। volatile का उपयोग यह सुनिश्चित करता है कि क्षेत्र का मूल्य सबसे हाल का मूल्य है जो उपलब्ध है, और मूल्य उस कैशिंग के अधीन नहीं है जो गैर-वाष्पशील मान हैं।

प्रत्येक चर को चिह्नित करना अच्छा है, जो कई थ्रेड्स द्वारा volatile रूप में उपयोग किया जा सकता है, ताकि पीछे के दृश्यों के अनुकूलन के कारण अप्रत्याशित व्यवहार को रोका जा सके। निम्नलिखित कोड ब्लॉक पर विचार करें:

public class Example
{
    public int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler will optimize this to y = 15
        var y = x + 10;

        /* the value of x will always be the current value, but y will always be "15" */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

उपरोक्त कोड-ब्लॉक में, कंपाइलर x = 5 और y = x + 10 स्टेटमेंट को पढ़ता है और निर्धारित करता है कि y का मान हमेशा 15. के रूप में समाप्त होगा। इस प्रकार, यह अंतिम स्टेटमेंट को y = 15 रूप में ऑप्टिमाइज़ करेगा। हालांकि, चर x वास्तव में एक public क्षेत्र है और x का मान इस क्षेत्र पर अलग-अलग थ्रेड अभिनय के माध्यम से रनटाइम पर संशोधित किया जा सकता है। अब इस संशोधित कोड-ब्लॉक पर विचार करें। ध्यान दें कि फ़ील्ड x अब volatile रूप में घोषित किया गया है।

public class Example
{
    public volatile int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler no longer optimizes this statement
        var y = x + 10;

        /* the value of x and y will always be the correct values */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

अब, कंपाइलर फ़ील्ड x पढ़े गए उपयोगों के लिए देखता है और यह सुनिश्चित करता है कि फ़ील्ड का वर्तमान मान हमेशा पुनर्प्राप्त किया जाता है। यह सुनिश्चित करता है कि भले ही इस क्षेत्र में कई थ्रेड्स पढ़ और लिख रहे हों, लेकिन x का वर्तमान मान हमेशा प्राप्त होता है।

volatile उपयोग केवल class एस या struct एस के भीतर खेतों पर किया जा सकता है। निम्नलिखित मान्य नहीं है :

public void MyMethod()
{
    volatile int x;
}

volatile केवल निम्नलिखित प्रकारों के क्षेत्रों पर लागू किया जा सकता है:

  • संदर्भ प्रकार या सामान्य प्रकार के पैरामीटर जिन्हें संदर्भ प्रकार कहा जाता है
  • जैसे आदिम प्रकार sbyte , byte , short , ushort , int , uint , char , float , और bool
  • के आधार पर enums प्रकार byte , sbyte , short , ushort , int या uint
  • IntPtr और UIntPtr

टिप्पणियों:

  • volatile संशोधक का उपयोग आमतौर पर एक क्षेत्र के लिए किया जाता है जो एक्सेस को अनुक्रमित करने के लिए लॉक स्टेटमेंट का उपयोग किए बिना कई थ्रेड्स द्वारा एक्सेस किया जाता है।
  • volatile कीवर्ड को संदर्भ प्रकारों के क्षेत्रों पर लागू किया जा सकता है
  • volatile कीवर्ड 32-बिट प्लेटफॉर्म परमाणु पर 64-बिट प्राइमेटिव पर परिचालन नहीं करेगा। इन प्लेटफ़ॉर्म पर सुरक्षित मल्टी-थ्रेडेड एक्सेस के लिए इंटरलॉक किए गए ऑपरेशन जैसे Interlocked.Read और Interlocked.Exchange उपयोग अभी भी किया जाना चाहिए।

तय

फिक्स्ड स्टेटमेंट एक स्थान पर मेमोरी को ठीक करता है। स्मृति में वस्तुएं आमतौर पर घूमती रहती हैं, इससे कचरा संग्रह संभव हो जाता है। लेकिन जब हम मेमोरी पतों के लिए असुरक्षित पॉइंटर्स का उपयोग करते हैं, तो उस मेमोरी को स्थानांतरित नहीं करना चाहिए।

  • हम यह सुनिश्चित करने के लिए निर्धारित कथन का उपयोग करते हैं कि कचरा संग्राहक स्ट्रिंग डेटा को स्थानांतरित नहीं करता है।

निश्चित चर

var myStr = "Hello world!";

fixed (char* ptr = myStr)
{
    // myStr is now fixed (won't be [re]moved by the Garbage Collector).
    // We can now do something with ptr.
}

एक असुरक्षित संदर्भ में उपयोग किया जाता है।

निश्चित ऐरे आकार

unsafe struct Example
{
    public fixed byte SomeField[8];
    public fixed char AnotherField[64];
}

fixed केवल एक struct में खेतों पर इस्तेमाल किया जा सकता है (एक असुरक्षित संदर्भ में भी इस्तेमाल किया जाना चाहिए)।

चूक

कक्षाओं के लिए, इंटरफेस, प्रतिनिधि, सरणी, null (जैसे int?) और सूचक प्रकार, default(TheType) null देता है:

class MyClass {}
Debug.Assert(default(MyClass) == null);
Debug.Assert(default(string) == null);

default(TheType) और default(TheType) , default(TheType) new TheType() के समान ही लौटाता है:

struct Coordinates
{
    public int X { get; set; }
    public int Y { get; set; }
}

struct MyStruct
{
    public string Name { get; set; }
    public Coordinates Location { get; set; }
    public Coordinates? SecondLocation { get; set; }
    public TimeSpan Duration { get; set; }
}

var defaultStruct = default(MyStruct);
Debug.Assert(defaultStruct.Equals(new MyStruct()));
Debug.Assert(defaultStruct.Location.Equals(new Coordinates()));
Debug.Assert(defaultStruct.Location.X == 0);
Debug.Assert(defaultStruct.Location.Y == 0);
Debug.Assert(defaultStruct.SecondLocation == null);
Debug.Assert(defaultStruct.Name == null);
Debug.Assert(defaultStruct.Duration == TimeSpan.Zero);

default(T) तब विशेष रूप से उपयोगी हो सकता है जब T एक सामान्य पैरामीटर हो, जिसके लिए कोई बाधा यह निर्धारित करने के लिए मौजूद न हो कि T एक संदर्भ प्रकार है या उदाहरण के लिए मान:

public T GetResourceOrDefault<T>(string resourceName)
{
   if (ResourceExists(resourceName))
   {
      return (T)GetResource(resourceName);
   }
   else
   {
      return default(T);
   }
}

सिफ़ पढ़िये

readonly खोजशब्द एक क्षेत्र संशोधक है। जब किसी क्षेत्र की घोषणा में एक आसानी से readonly शामिल होता है, तो उस क्षेत्र में असाइनमेंट केवल घोषणा के हिस्से के रूप में या उसी कक्षा में एक कंस्ट्रक्टर में हो सकता है।

readonly कीवर्ड से अलग है const कीवर्ड। एक const फ़ील्ड को केवल क्षेत्र की घोषणा पर आरंभीकृत किया जा सकता है। एक readonly क्षेत्र या तो घोषणा पर या एक निर्माता में प्रारंभ किया जा सकता है। इसलिए, readonly खेतों में इस्तेमाल किया निर्माता के आधार पर विभिन्न मान हो सकते हैं।

निर्भरता को इंजेक्ट करते समय अक्सर readonly कीवर्ड का उपयोग किया जाता है।

class Person
{
    readonly string _name;
    readonly string _surname = "Surname";

    Person(string name)
    {
        _name = name;
    }
    void ChangeName()
    {
        _name = "another name"; // Compile error
        _surname = "another surname"; // Compile error
    }
}

नोट: एक क्षेत्र केवल पढ़ने के लिए की घोषणा अचल स्थिति संकेत नहीं करता है। यदि फ़ील्ड एक संदर्भ प्रकार है, तो ऑब्जेक्ट की सामग्री को बदला जा सकता है। केवल पढ़ने के लिए आम तौर पर वस्तु ओवरराइट और केवल उस वस्तु की इन्स्टेन्शियशन दौरान निर्धारित किये जाने से होने को रोकने के लिए प्रयोग किया जाता है।

नोट: कंस्ट्रक्टर के अंदर एक रीडोनॉली फ़ील्ड को पुन: असाइन किया जा सकता है

public class Car
{
    public double Speed {get; set;}
}

//In code

private readonly Car car = new Car();

private void SomeMethod()
{
    car.Speed = 100;
}

जैसा

as कीवर्ड एक डाली के समान एक ऑपरेटर है। एक डाली संभव नहीं है, तो का उपयोग कर as पैदा करता null बल्कि एक में जिसके परिणामस्वरूप से InvalidCastException

expression as type की expression is type ? (type)expression : (type)null बराबर expression is type ? (type)expression : (type)null चेतावनी के साथ कि as संदर्भ रूपांतरण, नल रूपांतरण, और मुक्केबाजी रूपांतरण पर ही मान्य है। उपयोगकर्ता-परिभाषित रूपांतरण समर्थित नहीं हैं; इसके बजाय एक नियमित कलाकार का उपयोग किया जाना चाहिए।

ऊपर के विस्तार के लिए, कंपाइलर कोड उत्पन्न करता है जैसे कि expression का केवल एक बार मूल्यांकन किया जाएगा और एकल डायनामिक प्रकार की जांच (ऊपर के नमूने में दो के विपरीत) का उपयोग करेगा।

as उपयोगी होता है जब कई प्रकार की सुविधा के लिए एक बहस की उम्मीद हो सकती है। विशेष रूप से यह उपयोगकर्ता कई विकल्प देता है - बल्कि हर संभावना के साथ की जाँच की तुलना में is कास्टिंग से पहले, या बस कास्टिंग और अपवादों को पकड़ने। किसी ऑब्जेक्ट को कास्टिंग / चेक करते समय 'के रूप में' का उपयोग करना सबसे अच्छा अभ्यास है जो केवल एक अनबॉक्सिंग दंड का कारण होगा। उपयोग करना जाँच करना is , फिर कास्टिंग दो अनबॉक्सिंग दंड का कारण होगा।

यदि किसी तर्क को एक विशिष्ट प्रकार का उदाहरण माना जाता है, तो एक नियमित कलाकार को प्राथमिकता दी जाती है क्योंकि उसका उद्देश्य पाठक के लिए अधिक स्पष्ट है।

क्योंकि कॉल के as null पैदा कर सकता है, हमेशा एक NullReferenceException से बचने के लिए परिणाम की जाँच करें।

उदाहरण उपयोग

object something = "Hello";
Console.WriteLine(something as string);        //Hello
Console.Writeline(something as Nullable<int>); //null
Console.WriteLine(something as int?);          //null

//This does NOT compile:
//destination type must be a reference type (or a nullable value type)
Console.WriteLine(something as int);

.NET फिडल पर लाइव डेमो

का उपयोग किए बिना समतुल्य उदाहरण as :

Console.WriteLine(something is string ? (string)something : (string)null);

यह कस्टम कक्षाओं में Equals कार्य को ओवरराइड करते समय उपयोगी है।

class MyCustomClass
{

    public override bool Equals(object obj)
    {
        MyCustomClass customObject = obj as MyCustomClass;

        // if it is null it may be really null
        // or it may be of a different type
        if (Object.ReferenceEquals(null, customObject))
        {
            // If it is null then it is not equal to this instance.
            return false;
        }

        // Other equality controls specific to class
    }

}

है

जाँचता है कि क्या कोई वस्तु किसी दिए गए प्रकार के साथ संगत है, अर्थात यदि कोई वस्तु BaseInterface प्रकार का उदाहरण है, या एक प्रकार जो BaseInterface से प्राप्त होता है:

interface BaseInterface {}
class BaseClass : BaseInterface {}
class DerivedClass : BaseClass {}

var d = new DerivedClass();
Console.WriteLine(d is DerivedClass);  // True
Console.WriteLine(d is BaseClass);     // True
Console.WriteLine(d is BaseInterface); // True
Console.WriteLine(d is object);        // True
Console.WriteLine(d is string);        // False

var b = new BaseClass();
Console.WriteLine(b is DerivedClass);  // False
Console.WriteLine(b is BaseClass);     // True
Console.WriteLine(b is BaseInterface); // True
Console.WriteLine(b is object);        // True
Console.WriteLine(b is string);        // False

यदि कास्ट का उद्देश्य ऑब्जेक्ट का उपयोग करना है, तो कीवर्ड के as उपयोग करना सबसे अच्छा अभ्यास है '

interface BaseInterface {}
class BaseClass : BaseInterface {}
class DerivedClass : BaseClass {}

var d = new DerivedClass();
Console.WriteLine(d is DerivedClass);  // True - valid use of 'is'
Console.WriteLine(d is BaseClass);     // True - valid use of 'is'

if(d is BaseClass){
    var castedD = (BaseClass)d;
    castedD.Method(); // valid, but not best practice
}

var asD = d as BaseClass;

if(asD!=null){
    asD.Method(); //prefered method since you incur only one unboxing penalty
}

लेकिन, C # 7 pattern matching सुविधा से एक प्रकार की जांच करने और एक ही समय में एक नया चर घोषित करने के लिए ऑपरेटर का विस्तार होता है। C # 7 के साथ समान कोड भाग:

7.0
if(d is BaseClass asD ){
    asD.Method();
}

प्रकार का

वस्तु का Type लौटाता है, उसे तत्काल करने की आवश्यकता के बिना।

Type type = typeof(string);
Console.WriteLine(type.FullName); //System.String
Console.WriteLine("Hello".GetType() == type); //True
Console.WriteLine("Hello".GetType() == typeof(string)); //True

स्थिरांक

const का उपयोग उन मूल्यों का प्रतिनिधित्व करने के लिए किया जाता है जो कार्यक्रम के पूरे जीवनकाल में कभी नहीं बदलेंगे । इसका मान संकलन-समय से स्थिर है, जैसा कि आसानी से readonly कीवर्ड के विपरीत है, जिसका मूल्य रन-टाइम से निरंतर है।

उदाहरण के लिए, चूंकि प्रकाश की गति कभी नहीं बदलेगी, हम इसे स्थिर रूप से संग्रहीत कर सकते हैं।

const double c = 299792458;  // Speed of light

double CalculateEnergy(double mass)
{
    return mass * c * c;
}

यह अनिवार्य रूप से return mass * 299792458 * 299792458 होने के समान है, क्योंकि संकलक सीधे अपने निरंतर मूल्य के साथ c विकल्प देगा।

परिणामस्वरूप, c को एक बार घोषित किए जाने के बाद नहीं बदला जा सकता है। निम्नलिखित एक संकलन-समय त्रुटि उत्पन्न करेगा:

const double c = 299792458;  // Speed of light 

c = 500;  //compile-time error

एक निरंतर तरीकों के रूप में एक ही एक्सेस संशोधक के साथ उपसर्ग किया जा सकता है:

private const double c = 299792458;
public const double c = 299792458;
internal const double c = 299792458;

const मेंबर्स स्वभाव से static होते हैं। हालांकि स्पष्ट रूप से static का उपयोग करने की अनुमति नहीं है।

आप विधि-स्थानीय स्थिरांक भी परिभाषित कर सकते हैं:

double CalculateEnergy(double mass)
{
    const c = 299792458;
    return mass * c * c;
}

इन्हें किसी private या public कीवर्ड के साथ उपसर्ग नहीं किया जा सकता है, क्योंकि वे उस तरीके से स्थानीय रूप से स्थानीय हैं, जिसमें वे परिभाषित हैं।


सभी प्रकार का उपयोग एक const घोषणा में नहीं किया जा सकता है। मूल्य प्रकार है कि अनुमति दी जाती है, पूर्व निर्धारित प्रकार के होते हैं sbyte , byte , short , ushort , int , uint , long , ulong , char , float , double , decimal , bool , और सभी enum प्रकार के। अन्य मूल्य प्रकारों (जैसे TimeSpan या Guid ) के साथ const सदस्यों को घोषित करने की कोशिश संकलन-समय पर विफल हो जाएगी।

विशेष पूर्व-परिभाषित संदर्भ प्रकार string , किसी भी मूल्य के साथ स्थिरांक घोषित किए जा सकते हैं। अन्य सभी संदर्भ प्रकारों के लिए, स्थिरांक घोषित किए जा सकते हैं, लेकिन हमेशा मान null होना चाहिए।


क्योंकि const वैल्यू को कंपाइल-टाइम में जाना जाता है, उन्हें switch स्टेटमेंट में case लेबल के रूप में, वैकल्पिक मापदंडों के लिए मानक तर्क के रूप में, विनिर्देशों को विशेषता के लिए तर्क के रूप में और इतने पर अनुमति दी जाती है।


यदि विभिन्न विधानसभाओं में const वैल्यू का उपयोग किया जाता है, तो संस्करण के साथ देखभाल की जानी चाहिए। उदाहरण के लिए, यदि असेंबली ए public const int MaxRetries = 3; परिभाषित करता है public const int MaxRetries = 3; , और असेंबली B उस स्थिरांक का उपयोग करता है, तो यदि MaxRetries का मान बाद में असेंबली A में 5 में बदल दिया जाता है (जो तब पुन: संकलित किया जाता है), तो यह परिवर्तन असेंबली B में तब तक प्रभावी नहीं होगा जब तक असेंबली B को पुन: संकलित नहीं किया जाता है (साथ में ए के नए संस्करण के लिए एक संदर्भ)।

कारण है कि, अगर एक मूल्य के कार्यक्रम के भविष्य के संशोधन में बदल सकता है, और अगर मूल्य सार्वजनिक रूप से दिखाई की जरूरत है, कि मूल्य की घोषणा नहीं करते हैं const जब तक आप जानते हैं कि सभी निर्भर विधानसभाओं फिर से संकलित जब भी कुछ बदल गया है हो जाएगा। वैकल्पिक उपयोग कर रहा है static readonly के बजाय const है, जो रनटाइम पर हल हो गई है।

नाम स्थान

namespace कीवर्ड एक संगठन निर्माण है जो हमें यह समझने में मदद करता है कि एक कोडबेस की व्यवस्था कैसे की जाती है। C # में Namespaces एक भौतिक फ़ोल्डर में होने के बजाय वर्चुअल स्पेस हैं।

namespace StackOverflow
{
    namespace Documentation
    {
        namespace CSharp.Keywords
        {
            public class Program
            {
                public static void Main()
                {
                    Console.WriteLine(typeof(Program).Namespace);
                    //StackOverflow.Documentation.CSharp.Keywords
                }
            }
        }
    }
}

C # में Namespaces को chained syntax में भी लिखा जा सकता है। निम्नलिखित ऊपर के बराबर है:

namespace StackOverflow.Documentation.CSharp.Keywords
{
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine(typeof(Program).Namespace);
            //StackOverflow.Documentation.CSharp.Keywords
        }
    }
}

कोशिश करो, पकड़, अंत में, फेंक दो

try , catch , finally , और throw आप अपने कोड में अपवाद को संभालने के लिए अनुमति देते हैं।

var processor = new InputProcessor();

// The code within the try block will be executed. If an exception occurs during execution of
// this code, execution will pass to the catch block corresponding to the exception type.
try 
{
    processor.Process(input);
}
// If a FormatException is thrown during the try block, then this catch block
// will be executed.
catch (FormatException ex)
{
    // Throw is a keyword that will manually throw an exception, triggering any catch block that is
    // waiting for that exception type. 
    throw new InvalidOperationException("Invalid input", ex);
}
// catch can be used to catch all or any specific exceptions. This catch block,
// with no type specified, catches any exception that hasn't already been caught
// in a prior catch block.
catch
{
    LogUnexpectedException(); 
    throw; // Re-throws the original exception.
}
// The finally block is executed after all try-catch blocks have been; either after the try has
// succeeded in running all commands or after all exceptions have been caught. 
finally
{
    processor.Dispose();
}

नोट: return कीवर्ड का उपयोग try ब्लॉक में किया जा सकता है, और finally ब्लॉक को अभी भी निष्पादित किया जाएगा (लौटने से ठीक पहले)। उदाहरण के लिए:

try 
{
    connection.Open();
    return connection.Get(query);
} 
finally 
{
    connection.Close();
}

connection.Close() के परिणाम से पहले स्टेटमेंट connection.Close() । क्लोज connection.Close() निष्पादित होगा। गेट connection.Get(query) वापस आ गया है।

जारी रखें

एन्क्लोज़िंग लूप निर्माण के अगले पुनरावृत्ति के लिए तुरंत पास नियंत्रण (के लिए, फ़ॉरच, डू, जबकि):

for (var i = 0; i < 10; i++)
{
    if (i < 5)
    {
        continue;
    }
    Console.WriteLine(i);
}

आउटपुट:

5
6
7
8
9

.NET फिडल पर लाइव डेमो

var stuff = new [] {"a", "b", null, "c", "d"};

foreach (var s in stuff)
{
    if (s == null)
    {
        continue;
    }           
    Console.WriteLine(s);
}

आउटपुट:



सी

.NET फिडल पर लाइव डेमो

रेफरी, बाहर

ref और out कीवर्ड तर्क को संदर्भ द्वारा पारित करते हैं, न कि मूल्य द्वारा। मूल्य प्रकारों के लिए, इसका मतलब है कि चर के मूल्य को कैली द्वारा बदला जा सकता है।

int x = 5;
ChangeX(ref x);
// The value of x could be different now

संदर्भ प्रकारों के लिए, चर में उदाहरण को न केवल संशोधित किया जा सकता है (जैसा कि ref बिना मामला है), लेकिन इसे पूरी तरह से भी बदला जा सकता है:

Address a = new Address();
ChangeFieldInAddress(a);
// a will be the same instance as before, even if it is modified
CreateANewInstance(ref a);
// a could be an entirely new instance now

out और ref कीवर्ड के बीच मुख्य अंतर यह है कि ref को चर को कॉलर द्वारा इनिशियलाइज़ करने की आवश्यकता होती है, जबकि out उस जिम्मेदारी को कैली को पास करता है।

out पैरामीटर का उपयोग करने के लिए, विधि परिभाषा और कॉलिंग विधि दोनों को स्पष्ट रूप से out कीवर्ड का उपयोग करना चाहिए।

int number = 1;
Console.WriteLine("Before AddByRef: " + number); // number = 1
AddOneByRef(ref number);
Console.WriteLine("After AddByRef: " + number);  // number = 2
SetByOut(out number);
Console.WriteLine("After SetByOut: " + number);  // number = 34

void AddOneByRef(ref int value)
{
    value++;
}

void SetByOut(out int value)
{
    value = 34;
}

.NET फिडल पर लाइव डेमो

निम्नलिखित संकलन नहीं करता, क्योंकि out मानकों (इसे प्रयोग संकलन होगा विधि रिटर्न से पहले सौंपा एक मान होना चाहिए ref के बजाय):

void PrintByOut(out int value)
{
    Console.WriteLine("Hello!");
}

सामान्य संशोधक के रूप में कीवर्ड का उपयोग करना

out कीवर्ड भी जब सामान्य इंटरफेस और प्रतिनिधियों को परिभाषित सामान्य प्रकार पैरामीटर में इस्तेमाल किया जा सकता है। इस स्थिति में, out कीवर्ड निर्दिष्ट करता है कि टाइप पैरामीटर सहसंयोजक है।

कोवरियन आपको सामान्य पैरामीटर द्वारा निर्दिष्ट की तुलना में अधिक व्युत्पन्न प्रकार का उपयोग करने में सक्षम बनाता है। यह वर्गों के निहितार्थ रूपांतरण के लिए अनुमति देता है जो वैरिएबल इंटरफेस को लागू करता है और प्रतिनिधि प्रकार के अंतर्निहित रूपांतरण को लागू करता है। Covariance और contravariance संदर्भ प्रकारों के लिए समर्थित हैं, लेकिन वे मूल्य प्रकारों के लिए समर्थित नहीं हैं। - MSDN

//if we have an interface like this
interface ICovariant<out R> { }

//and two variables like
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();

// then the following statement is valid
// without the out keyword this would have thrown error
iobj = istr; // implicit conversion occurs here

जाँच की गई, अनियंत्रित

checked और unchecked कीवर्ड परिभाषित करते हैं कि ऑपरेशन गणितीय अतिप्रवाह को कैसे संभालते हैं। checked और unchecked कीवर्ड के संदर्भ में "ओवरफ्लो" तब होता है जब एक पूर्णांक अंकगणितीय ऑपरेशन का परिणाम एक मूल्य में होता है जो लक्ष्य डेटा प्रकार का प्रतिनिधित्व करने की तुलना में परिमाण में अधिक होता है।

अतिप्रवाह एक के भीतर होती है जब checked ब्लॉक (या जब संकलक उपयोग अंकगणित जाँच की विश्व स्तर पर सेट किया जाता है), एक अपवाद अवांछित व्यवहार की चेतावनी देने में फेंक दिया है। इस बीच, एक unchecked ब्लॉक में, अतिप्रवाह चुप है: कोई अपवाद नहीं फेंका जाता है, और मूल्य बस विपरीत सीमा के चारों ओर लपेटेगा। इससे कीड़े को खोजने के लिए सूक्ष्म, कठिन हो सकता है।

चूँकि अधिकांश अंकगणितीय संक्रियाएँ ऐसे मानों पर की जाती हैं जो अतिप्रवाह के लिए बड़े या छोटे नहीं होते हैं, अधिकांश समय, किसी ब्लॉक को checked रूप में स्पष्ट रूप से परिभाषित करने की आवश्यकता नहीं होती checked । अनबाउंड इनपुट पर अंकगणित करते समय सावधानी बरतने की आवश्यकता होती है जो कि अतिप्रवाह का कारण बन सकता है, उदाहरण के लिए पुनरावर्ती कार्यों में अंकगणित करते समय या उपयोगकर्ता इनपुट लेते समय।

न तो checked और न ही unchecked फ्लोटिंग पॉइंट अंकगणितीय संचालन को प्रभावित किया।

जब एक ब्लॉक या अभिव्यक्ति को unchecked घोषित किया जाता है, तो इसके अंदर किसी भी अंकगणितीय संचालन को त्रुटि पैदा किए बिना ओवरफ्लो करने की अनुमति दी जाती है। एक उदाहरण जहां यह व्यवहार वांछित है , एक चेकसम की गणना होगी, जहां गणना के दौरान मूल्य को "चारों ओर लपेटने" की अनुमति है:

byte Checksum(byte[] data) {
    byte result = 0;
    for (int i = 0; i < data.Length; i++) {
        result = unchecked(result + data[i]); // unchecked expression
    }
    return result;
}

unchecked लिए सबसे आम उपयोगों में से एक है object.GetHashCode() लिए एक कस्टम ओवरराइड लागू करना। object.GetHashCode() , एक प्रकार का चेकसम। आप इस प्रश्न के उत्तर में कीवर्ड का उपयोग देख सकते हैं: एक ओवरराइड System.Object.GetHashCode के लिए सबसे अच्छा एल्गोरिथ्म क्या है?

जब एक ब्लॉक या अभिव्यक्ति को checked रूप में घोषित किया जाता checked , तो किसी भी अंकगणितीय ऑपरेशन के कारण जो अतिप्रवाह होता है, एक OverflowException फेंका जाता है।

int SafeSum(int x, int y) {
    checked { // checked block
        return x + y; 
    }
}

चेक और अनियंत्रित दोनों ही ब्लॉक और एक्सप्रेशन फॉर्म में हो सकते हैं।

चेक किए गए और अनियंत्रित ब्लॉक नामक विधियों को प्रभावित नहीं करते हैं, केवल ऑपरेटर वर्तमान विधि में सीधे कॉल करते हैं। उदाहरण के लिए, Enum.ToObject() , Convert.ToInt32() , और उपयोगकर्ता-परिभाषित ऑपरेटर कस्टम चेक / अनियंत्रित संदर्भों से प्रभावित नहीं होते हैं।

नोट : डिफ़ॉल्ट अतिप्रवाह डिफ़ॉल्ट व्यवहार (चेक बनाम अनियंत्रित) प्रोजेक्ट गुण में या के माध्यम से / जाँच की जा सकती है [+ | -] कमांड लाइन स्विच। डिबग बिल्ड और रिलीज़ बिल्ड के लिए अनचेक किए गए ऑपरेशनों की जाँच करना डिफ़ॉल्ट है। checked और unchecked कीवर्ड का उपयोग तब ही किया जाएगा जहां एक डिफ़ॉल्ट दृष्टिकोण लागू नहीं होता है और शुद्धता सुनिश्चित करने के लिए आपको एक स्पष्ट व्यवहार की आवश्यकता होती है।

के लिए जाओ

goto का उपयोग कोड के अंदर एक विशिष्ट लाइन पर जाने के लिए किया जा सकता है, जो एक लेबल द्वारा निर्दिष्ट किया गया है।

goto एक के रूप में:

लेबल:

void InfiniteHello()
{
    sayHello:
    Console.WriteLine("Hello!");
    goto sayHello;
}

.NET फिडल पर लाइव डेमो

केस स्टेटमेंट:

enum Permissions { Read, Write };

switch (GetRequestedPermission())
{
    case Permissions.Read:
        GrantReadAccess();
        break;

    case Permissions.Write:
        GrantWriteAccess();
        goto case Permissions.Read; //People with write access also get read
}

.NET फिडल पर लाइव डेमो

यह एक स्विच स्टेटमेंट में कई व्यवहारों को निष्पादित करने में विशेष रूप से उपयोगी है, क्योंकि C # फॉल-थ्रू केस ब्लॉक का समर्थन नहीं करता है।

अपवाद रिट्री

var exCount = 0;
retry:
try
{
    //Do work
}
catch (IOException)
{
    exCount++;
    if (exCount < 3)
    {
        Thread.Sleep(100);
        goto retry;
    }
    throw;
}

.NET फिडल पर लाइव डेमो

कई भाषाओं के समान, नीचे दिए गए मामलों को छोड़कर गोटो कीवर्ड का उपयोग हतोत्साहित किया जाता है।

goto का वैध उपयोग जो C # पर लागू होता है:

  • फॉल-थ्रू केस इन स्विच स्टेटमेंट।

  • बहु-स्तरीय विराम। LINQ का उपयोग अक्सर इसके बजाय किया जा सकता है, लेकिन आमतौर पर इसका प्रदर्शन खराब होता है।

  • निचले स्तर की वस्तुओं के साथ काम करने पर संसाधन का बहिष्कार। सी # में, निम्न-स्तरीय वस्तुओं को आमतौर पर अलग-अलग वर्गों में लपेटा जाना चाहिए।

  • परिमित राज्य मशीनें, उदाहरण के लिए, पार्सर; आंतरिक रूप से संकलक द्वारा उपयोग किया जाता है उत्पन्न async / प्रतीक्षित राज्य मशीनों।

enum

enum कीवर्ड संकलक को बताता है कि यह वर्ग सार वर्ग Enum से विरासत में मिला है, बिना प्रोग्रामर को स्पष्ट रूप से विरासत में मिला है। Enum ValueType का एक वंशज है, जिसका नाम नामित स्थिरांक के अलग सेट के साथ उपयोग करने के लिए है।

public enum DaysOfWeek
{
    Monday,
    Tuesday,
}

आप वैकल्पिक रूप से प्रत्येक के लिए एक विशिष्ट मान निर्दिष्ट कर सकते हैं (या उनमें से कुछ):

public enum NotableYear
{
   EndOfWwI = 1918;
   EnfOfWwII = 1945,
}

इस उदाहरण में मैंने 0 के लिए एक मान छोड़ दिया है, यह आमतौर पर एक बुरा अभ्यास है। एक enum हमेशा स्पष्ट रूपांतरण द्वारा उत्पादित एक डिफ़ॉल्ट मान होगा (YourEnumType) 0 , जहां YourEnumType अपने घोषित है enume प्रकार। परिभाषित 0 के मान के बिना, enum में दीक्षा में परिभाषित मूल्य नहीं होगा।

के डिफ़ॉल्ट अंतर्निहित प्रकार enum है int , आप सहित किसी भी अभिन्न प्रकार के अंतर्निहित प्रकार बदल सकते हैं byte , sbyte , short , ushort , int , uint , long और ulong । नीचे अंतर्निहित प्रकार byte साथ एक एनम है:

enum Days : byte
{
    Sunday = 0,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

यह भी ध्यान दें कि आप किसी कलाकार के साथ अंतर्निहित प्रकार से / में परिवर्तित कर सकते हैं:

int value = (int)NotableYear.EndOfWwI;

इन कारणों से आप हमेशा बेहतर जांच करेंगे कि लाइब्रेरी के कार्यों को उजागर करते समय कोई enum मान्य है या नहीं:

void PrintNotes(NotableYear year)
{
    if (!Enum.IsDefined(typeof(NotableYear), year))
        throw InvalidEnumArgumentException("year", (int)year, typeof(NotableYear));

    // ...
}

आधार

base कीवर्ड का उपयोग बेस क्लास के सदस्यों तक पहुंचने के लिए किया जाता है। यह आमतौर पर आभासी तरीकों के आधार कार्यान्वयन को कॉल करने के लिए या निर्दिष्ट करने के लिए उपयोग किया जाता है कि किस आधार निर्माता को बुलाया जाना चाहिए।

एक कंस्ट्रक्टर चुनना

public class Child : SomeBaseClass {
    public Child() : base("some string for the base class")
    {
    }
}

public class SomeBaseClass {
    public SomeBaseClass()
    {
        // new Child() will not call this constructor, as it does not have a parameter
    }
    public SomeBaseClass(string message)
    {
        // new Child() will use this base constructor because of the specified parameter in Child's constructor
        Console.WriteLine(message);
    }
}

आभासी पद्धति का आधार कार्यान्वयन कहलाता है

public override void SomeVirtualMethod() {
    // Do something, then call base implementation
    base.SomeVirtualMethod();
}

किसी भी विधि से आधार कार्यान्वयन को कॉल करने के लिए आधार कीवर्ड का उपयोग करना संभव है। यह विधि कॉल को सीधे आधार कार्यान्वयन से जोड़ता है, जिसका अर्थ है कि भले ही नए बच्चे कक्षाएं एक आभासी विधि को ओवरराइड करती हैं, फिर भी आधार कार्यान्वयन को बुलाया जाएगा इसलिए इसे सावधानी के साथ उपयोग करने की आवश्यकता है।

public class Parent
{
    public virtual int VirtualMethod()
    {
        return 1;
    }
}

public class Child : Parent
{
    public override int VirtualMethod() {
        return 11;
    }

    public int NormalMethod()
    {
        return base.VirtualMethod();
    }

    public void CallMethods()
    {
        Assert.AreEqual(11, VirtualMethod());

        Assert.AreEqual(1, NormalMethod());
        Assert.AreEqual(1, base.VirtualMethod());
    }
}

public class GrandChild : Child
{
    public override int VirtualMethod()
    {
        return 21;
    }

    public void CallAgain()
    {
        Assert.AreEqual(21, VirtualMethod());
        Assert.AreEqual(11, base.VirtualMethod());

        // Notice that the call to NormalMethod below still returns the value
        // from the extreme base class even though the method has been overridden
        // in the child class.
        Assert.AreEqual(1, NormalMethod());
    }
}

प्रत्येक के लिए

foreach का उपयोग सरणी के तत्वों या संग्रह के भीतर वस्तुओं पर पुनरावृति करने के लिए किया जाता है जो IEnumerable ments को लागू करता है।

var lines = new string[] { 
    "Hello world!", 
    "How are you doing today?", 
    "Goodbye"
};

foreach (string line in lines)
{
    Console.WriteLine(line);
}

यह आउटपुट करेगा

"नमस्ते दुनिया!"
"आप आज कैसे हैं?"
"अलविदा"

.NET फिडल पर लाइव डेमो

आप ब्रेक कीवर्ड का उपयोग करके किसी भी बिंदु पर foreach लूप से बाहर निकल सकते हैं या जारी कीवर्ड का उपयोग करके अगले पुनरावृत्ति पर जा सकते हैं।

var numbers = new int[] {1, 2, 3, 4, 5, 6};

foreach (var number in numbers)
{
    // Skip if 2
    if (number == 2)
        continue;

    // Stop iteration if 5
    if (number == 5)
        break;

    Console.Write(number + ", ");
}

// Prints: 1, 3, 4, 

.NET फिडल पर लाइव डेमो

ध्यान दें कि पुनरावृत्ति का क्रम केवल कुछ संग्रह जैसे सरणियों और List लिए गारंटी है, लेकिन कई अन्य संग्रह के लिए गारंटी नहीं है


✝ जबकि IEnumerable का उपयोग आमतौर पर गणना करने योग्य संग्रह को इंगित करने के लिए किया जाता है, foreach केवल यह आवश्यक है कि संग्रह सार्वजनिक रूप से object GetEnumerator() विधि को उजागर करे, जो एक ऐसी वस्तु को लौटाए जो bool MoveNext() तरीका bool MoveNext() और ऑब्जेक्ट को उजागर करती है object Current { get; } संपत्ति।

पैरामीटर

params एक पैरामीटर पैरामीटर को चर की एक संख्या प्राप्त करने की अनुमति देता है, अर्थात उस पैरामीटर के लिए शून्य, एक या कई तर्क दिए जाते हैं।

static int AddAll(params int[] numbers)
{
    int total = 0;
    foreach (int number in numbers)
    {
        total += number;
    }
    
    return total;
}

इस विधि अब का एक विशिष्ट सूची के साथ कहा जा सकता है int तर्क या ints की एक सरणी।

AddAll(5, 10, 15, 20);                // 50
AddAll(new int[] { 5, 10, 15, 20 });  // 50

params ज्यादा से ज्यादा दिखाई देना चाहिए एक बार और अगर इस्तेमाल किया, यह तर्क सूची में अंतिम होना चाहिए, भले ही सफल प्रकार सरणी की है कि अलग है।


जब params कीवर्ड का उपयोग करते समय कार्यों को ओवरलोड करते समय सावधान रहें। सी # params साथ अधिभार का उपयोग करने की कोशिश करने से पहले अधिक विशिष्ट अधिभार से मेल खाना पसंद करते हैं। उदाहरण के लिए यदि आपके पास दो तरीके हैं:

static double Add(params double[] numbers)
{
    Console.WriteLine("Add with array of doubles");
    double total = 0.0;
    foreach (double number in numbers)
    {
        total += number;
    }
    
    return total;
}

static int Add(int a, int b)
{
    Console.WriteLine("Add with 2 ints");
    return a + b;
}

तब विशिष्ट 2 तर्क अधिभार params अधिभार की कोशिश करने से पहले पूर्वता ले लेंगे।

Add(2, 3);      //prints "Add with 2 ints"
Add(2, 3.0);    //prints "Add with array of doubles" (doubles are not ints)
Add(2, 3, 4);   //prints "Add with array of doubles" (no 3 argument overload)

टूटना

एक लूप में (foreach, doeach, करते समय) break स्टेटमेंट अंतरतम लूप के निष्पादन को रोक देता है और उस पर कोड पर लौट आता है। इसके अलावा यह yield साथ उपयोग किया जा सकता है जिसमें यह निर्दिष्ट करता है कि एक पुनरावृत्ति समाप्त हो गई है।

for (var i = 0; i < 10; i++)
{
    if (i == 5)
    {
        break;
    }
    Console.WriteLine("This will appear only 5 times, as the break will stop the loop.");
}

.NET फिडल पर लाइव डेमो

foreach (var stuff in stuffCollection)
{
    if (stuff.SomeStringProp == null)
        break;
    // If stuff.SomeStringProp for any "stuff" is null, the loop is aborted.
    Console.WriteLine(stuff.SomeStringProp);
}

ब्रेक-स्टेट का उपयोग स्विच-केस निर्माण में किसी मामले या डिफ़ॉल्ट सेगमेंट को तोड़ने के लिए भी किया जाता है।

switch(a)
{
    case 5:
        Console.WriteLine("a was 5!");
        break;

    default:
        Console.WriteLine("a was something else!");
        break;
}

स्विच स्टेटमेंट में, प्रत्येक केस स्टेटमेंट के अंत में 'ब्रेक' कीवर्ड की आवश्यकता होती है। यह कुछ भाषाओं के विपरीत है जो श्रृंखला में अगले केस स्टेटमेंट के लिए 'गिरने' की अनुमति देते हैं। इसके लिए वर्कअराउंड में 'गोटो' स्टेटमेंट्स शामिल होंगे या 'केस' स्टेटमेंट्स को क्रमिक रूप से स्टैक करना होगा।

निम्नलिखित कोड नंबर 0, 1, 2, ..., 9 और अंतिम पंक्ति निष्पादित नहीं की जाएगी। yield break फ़ंक्शन के अंत का संकेत yield break है (न कि केवल एक लूप)।

public static IEnumerable<int> GetNumbers()
{
    int i = 0;
    while (true) {
        if (i < 10) {
            yield return i++;
        } else {
            yield break;
        }
    }
    Console.WriteLine("This line will not be executed");
}

.NET फिडल पर लाइव डेमो

ध्यान दें कि कुछ अन्य भाषाओं के विपरीत, C # में किसी विशेष ब्रेक को लेबल करने का कोई तरीका नहीं है। इसका मतलब है कि नेस्टेड लूप के मामले में, केवल अंतरतम लूप को रोक दिया जाएगा:

foreach (var outerItem in outerList)
{
    foreach (var innerItem in innerList)
    {
        if (innerItem.ShoudBreakForWhateverReason)
            // This will only break out of the inner loop, the outer will continue:
            break; 
    }
}

यदि आप यहां बाहरी पाश से बाहर निकलना चाहते हैं, तो आप कई अलग-अलग रणनीतियों में से एक का उपयोग कर सकते हैं, जैसे:

  • पूरे लूपिंग ढांचे से बाहर निकलने के लिए एक गोटो स्टेटमेंट।
  • एक विशिष्ट झंडा चर ( shouldBreak निम्न उदाहरण में) है कि बाहरी पाश की प्रत्येक यात्रा के अंत में जाँच की जा सकती।
  • अंतर लूप बॉडी में return स्टेटमेंट का उपयोग करने के लिए कोड को return से भरना, या पूरे नेस्टेड लूप संरचना से पूरी तरह से बचें।
bool shouldBreak = false;
while(comeCondition)
{
    while(otherCondition)
    {
        if (conditionToBreak)
        {
            // Either tranfer control flow to the label below...
            goto endAllLooping;

            // OR use a flag, which can be checked in the outer loop:
            shouldBreak = true;
        }
    }

    if(shouldBreakNow)
    {
        break; // Break out of outer loop if flag was set to true
    }
}

endAllLooping: // label from where control flow will continue

सार

कीवर्ड abstract के साथ चिह्नित एक क्लास को तत्काल नहीं किया जा सकता है।

एक वर्ग को सार के रूप में चिह्नित किया जाना चाहिए यदि इसमें सार सदस्य शामिल हैं या यदि यह सार सदस्यों को विरासत में मिला है जो इसे लागू नहीं करता है। एक वर्ग को सार के रूप में चिह्नित किया जा सकता है, भले ही कोई सार सदस्य शामिल न हों।

अमूर्त वर्गों को आमतौर पर बेस कक्षाओं के रूप में उपयोग किया जाता है जब कार्यान्वयन के कुछ हिस्से को किसी अन्य घटक द्वारा निर्दिष्ट करने की आवश्यकता होती है।

abstract class Animal 
{
    string Name { get; set; }
    public abstract void MakeSound();
}

public class Cat : Animal 
{
    public override void MakeSound()
    {
        Console.WriteLine("Meov meov");
    }
}

public class Dog : Animal 
{   
    public override void MakeSound()
    {
        Console.WriteLine("Bark bark");
    }
}

Animal cat = new Cat();       // Allowed due to Cat deriving from Animal
cat.MakeSound();              // will print out "Meov meov"    

Animal dog = new Dog();       // Allowed due to Dog deriving from Animal
dog.MakeSound();              // will print out "Bark bark"

Animal animal = new Animal(); // Not allowed due to being an abstract class

कीवर्ड abstract के साथ चिह्नित एक विधि, संपत्ति या घटना इंगित करती है कि उस सदस्य के लिए कार्यान्वयन एक उपवर्ग में प्रदान किए जाने की उम्मीद है। जैसा कि ऊपर उल्लेख किया गया है, अमूर्त सदस्य केवल अमूर्त कक्षाओं में दिखाई दे सकते हैं।

abstract class Animal 
{
   public abstract string Name { get; set; }
}

public class Cat : Animal 
{
    public override string Name { get; set; }
}

public class Dog : Animal 
{
    public override string Name { get; set; }
}

फ्लोट, डबल, दशमलव

नाव

float .NET डेटाटाइप System.Single लिए एक अन्य नाम है। यह IEEE 754 एकल-सटीक फ़्लोटिंग पॉइंट नंबरों को संग्रहीत करने की अनुमति देता है। यह डेटा प्रकार mscorlib.dll में मौजूद होता है, जो आपके द्वारा बनाते समय प्रत्येक C # प्रोजेक्ट द्वारा संदर्भित किया जाता है।

अनुमानित सीमा: -3.4 × 10 38 से 3.4 × 10 38

दशमलव सटीक: 6-9 महत्वपूर्ण अंक

संकेतन :

float f = 0.1259;
var f1 = 0.7895f; // f is literal suffix to represent float values 

यह ध्यान दिया जाना चाहिए कि float प्रकार अक्सर महत्वपूर्ण गोलाई त्रुटियों में परिणाम करता है। उन अनुप्रयोगों में जहां परिशुद्धता महत्वपूर्ण है, अन्य डेटा प्रकारों पर विचार किया जाना चाहिए।


दोहरा

double नेट डेटाप्रकार के लिए एक उपनाम है System.Double । यह एक डबल-सटीक 64-बिट फ्लोटिंग-पॉइंट संख्या का प्रतिनिधित्व करता है। यह डेटा mscorlib.dll में मौजूद है जो किसी भी C # प्रोजेक्ट में निहित है।

रेंज: × 5.0 × 10 24324 से 10 1.7 × 10 308

दशमलव सटीक: 15-16 महत्वपूर्ण अंक

संकेतन :

double distance = 200.34; // a double value
double salary = 245; // an integer implicitly type-casted to double value
var marks = 123.764D; // D is literal suffix to represent double values

दशमलव

decimal .NET डेटाटाइप System.Decimal का एक उपनाम है। यह एक कीवर्ड को दर्शाता है जो 128-बिट डेटा प्रकार को इंगित करता है। फ्लोटिंग-पॉइंट प्रकारों की तुलना में, दशमलव प्रकार में अधिक सटीकता और एक छोटी सी सीमा होती है, जो वित्तीय और मौद्रिक गणना के लिए उपयुक्त बनाती है। यह डेटा mscorlib.dll में मौजूद है जो किसी भी C # प्रोजेक्ट में निहित है।

रेंज: -7.9 × 10 28 से 7.9 × 10 28

दशमलव सटीक: 28-29 महत्वपूर्ण अंक

संकेतन :

decimal payable = 152.25m; // a decimal value
var marks = 754.24m; // m is literal suffix to represent decimal values

uint

एक अहस्ताक्षरित पूर्णांक , या यूंट , एक संख्यात्मक डेटाटाइप है जो केवल सकारात्मक पूर्णांक पकड़ सकता है। जैसा कि यह नाम से पता चलता है, यह एक 32-बिट पूर्णांक का प्रतिनिधित्व करता है। यूंट कीवर्ड स्वयं कॉमन टाइप सिस्टम प्रकार System.UInt32 लिए एक उपनाम है। यह डेटाटाइप mscorlib.dll में मौजूद है, जिसे आप बनाते समय प्रत्येक C # प्रोजेक्ट द्वारा संदर्भित किया जाता है। यह मेमोरी स्पेस के चार बाइट्स पर कब्जा कर लेता है।

निरुपित पूर्णांक 0 से 4,294,967,295 तक किसी भी मूल्य को पकड़ सकते हैं।

अहस्ताक्षरित पूर्णांक घोषित करने के लिए कैसे और अब नहीं के उदाहरण

uint i = 425697; // Valid expression, explicitly stated to compiler
var i1 = 789247U; // Valid expression, suffix allows compiler to determine datatype
uint x = 3.0; // Error, there is no implicit conversion

कृपया ध्यान दें: Microsoft के अनुसार, जहाँ भी संभव हो, int datatype का उपयोग करने की अनुशंसा की जाती है, क्योंकि uint डेटाटाइप CLS- अनुरूप नहीं है।

इस

this कीवर्ड क्लास (ऑब्जेक्ट) के वर्तमान उदाहरण को संदर्भित करता है। इस तरह एक ही नाम के दो चर, वर्ग-स्तर पर (एक क्षेत्र) और एक विधि के एक पैरामीटर (या स्थानीय चर) होने के कारण, प्रतिष्ठित किया जा सकता है।

public MyClass {
    int a;

    void set_a(int a)
    {
        //this.a refers to the variable defined outside of the method,
        //while a refers to the passed parameter.
        this.a = a;
    }
}

कीवर्ड के अन्य उपयोग गैर-स्थैतिक निर्माता अधिभार का पीछा कर रहे हैं:

public MyClass(int arg) : this(arg, null)
{
}

और लेखन सूचकांक :

public string this[int idx1, string idx2]
{
    get { /* ... */ }
    set { /* ... */ }
}

और विस्तार विधियों की घोषणा:

public static int Count<TItem>(this IEnumerable<TItem> source)
{
    // ...
}

यदि कोई स्थानीय चर या पैरामीटर के साथ कोई विरोध नहीं है, तो this शैली का मामला है कि यह उपयोग this या नहीं, इसलिए यह। this.MemberOfType और MemberOfType उस मामले में बराबर होगा। base कीवर्ड भी देखें।

ध्यान दें कि यदि वर्तमान उदाहरण पर एक एक्सटेंशन विधि को कॉल किया जाना है, तो this आवश्यक है। उदाहरण के लिए यदि आपका वर्ग किसी गैर-स्थैतिक विधि के अंदर है जो IEnumerable<> लागू करता है और आप एक्सटेंशन Count को पहले से कॉल करना चाहते हैं, तो आपको इसका उपयोग करना होगा:

this.Count()  // works like StaticClassForExtensionMethod.Count(this)

और this वहां छोड़ा नहीं जा सकता।

के लिये

सिंटैक्स: for (initializer; condition; iterator)

  • for पाश आमतौर पर इस्तेमाल किया जब पुनरावृत्तियों की संख्या में जाना जाता है है।
  • initializer खंड में कथन केवल एक बार चलते हैं, इससे पहले कि आप लूप में प्रवेश करें।
  • condition अनुभाग में एक बूलियन अभिव्यक्ति होती है जिसका मूल्यांकन प्रत्येक लूप पुनरावृत्ति के अंत में किया जाता है ताकि यह निर्धारित किया जा सके कि लूप बाहर निकलना चाहिए या फिर से चलना चाहिए।
  • iterator अनुभाग क्या लूप के शरीर के प्रत्येक यात्रा के बाद क्या होता परिभाषित करता है।

यह उदाहरण दिखाता है कि स्ट्रिंग के पात्रों पर पुनरावृति करने के for कैसे उपयोग किया जा सकता है:

string str = "Hello";
for (int i = 0; i < str.Length; i++)
{
    Console.WriteLine(str[i]);                
}

आउटपुट:

एच

एल
एल

.NET फिडल पर लाइव डेमो

कथन के for परिभाषित सभी अभिव्यक्तियाँ वैकल्पिक हैं; उदाहरण के लिए, अनंत लूप बनाने के लिए निम्न कथन का उपयोग किया जाता है:

for( ; ; )
{
    // Your code here
}

initializer खंड में कई चर हो सकते हैं, जब तक कि वे एक ही प्रकार के न हों। condition अनुभाग में किसी भी अभिव्यक्ति शामिल हो सकती है जिसका मूल्यांकन एक bool लिए किया जा सकता है। और iterator अनुभाग अल्पविराम द्वारा अलग किए गए कई कार्य कर सकता है:

string hello = "hello";
for (int i = 0, j = 1, k = 9; i < 3 && k > 0; i++, hello += i) {
    Console.WriteLine(hello);
}

आउटपुट:

नमस्कार
hello1
hello12

.NET फिडल पर लाइव डेमो

जबकि

while संचालक कोड के एक खंड पर पुनरावृत्ति करता है जब तक कि सशर्त क्वेरी झूठी नहीं होती या कोड एक goto , return , break या throw स्टेटमेंट के साथ बाधित होता है।

के लिए सिंटेक्स while कीवर्ड:

जबकि ( स्थिति ) { कोड ब्लॉक; }

उदाहरण:

int i = 0;
while (i++ < 5)
{
    Console.WriteLine("While is on loop number {0}.", i);
}

आउटपुट:

"लूप नंबर 1 पर है"
"जबकि लूप नंबर 2 पर है।"
"जबकि लूप नंबर 3 पर है"
"जबकि लूप नंबर 4 पर है।"
"जबकि लूप नंबर 5 पर है।"

.NET फिडल पर लाइव डेमो

एक लूप में प्रवेश नियंत्रित होता है , क्योंकि संलग्न कोड ब्लॉक के निष्पादन से पहले स्थिति की जांच की जाती है। इसका मतलब यह है कि अगर स्थिति गलत है तो लूप अपने बयानों को निष्पादित नहीं करेगा।

bool a = false;

while (a == true)
{
    Console.WriteLine("This will never be printed.");
}

कुछ बिंदु पर गलत होने का प्रावधान किए बिना while शर्त देने से एक अनंत या अंतहीन लूप हो जाएगा। जहां तक संभव हो, इससे बचा जाना चाहिए, हालांकि, जब आपको इसकी आवश्यकता होती है तो कुछ असाधारण परिस्थितियां हो सकती हैं।

आप इस तरह के एक लूप बना सकते हैं:

while (true)
{
//...
}

ध्यान दें कि C # कंपाइलर लूप को बदल देगा

while (true)
{
// ...
}

या

for(;;)
{
// ...
}

में

{
:label
// ...
goto label;
}

ध्यान दें कि थोड़ी देर के लूप की कोई भी स्थिति हो सकती है, चाहे वह कितनी भी जटिल हो, जब तक वह बूलियन वैल्यू (बूल) का मूल्यांकन (या रिटर्न) नहीं करता है। इसमें एक फ़ंक्शन भी हो सकता है जो बूलियन मान लौटाता है (जैसे कि एक फ़ंक्शन उसी प्रकार का मूल्यांकन करता है जैसे कि एक अभिव्यक्ति जैसे कि `a == x ')। उदाहरण के लिए,

while (AgriculturalService.MoreCornToPick(myFarm.GetAddress()))
{
    myFarm.PickCorn();
}

वापसी

MSDN: रिटर्न स्टेटमेंट उस पद्धति के निष्पादन को समाप्त करता है जिसमें यह दिखाई देता है और कॉलिंग विधि पर नियंत्रण लौटाता है। यह एक वैकल्पिक मान भी लौटा सकता है। यदि विधि एक शून्य प्रकार है, तो रिटर्न स्टेटमेंट छोड़ा जा सकता है।

public int Sum(int valueA, int valueB)
{
    return valueA + valueB;
}


public void Terminate(bool terminateEarly)
{
    if (terminateEarly) return; // method returns to caller if true was passed in
    else Console.WriteLine("Not early"); // prints only if terminateEarly was false
}

में

in कीवर्ड पर तीन का उपयोग करता है:

क) एक foreach स्टेटमेंट में सिंटैक्स के हिस्से के रूप में या एक LINQ क्वेरी में सिंटैक्स के हिस्से के रूप में

foreach (var member in sequence)
{
    // ...
}

बी) जेनेरिक इंटरफेस और जेनेरिक डेलीगेट के संदर्भ में प्रश्न में टाइप पैरामीटर के लिए विरोधाभासी संकेत है:

public interface IComparer<in T>
{
    // ...
}

c) LINQ क्वेरी के संदर्भ में उस संग्रह को संदर्भित करता है जिसे क्वेर किया जा रहा है

var query = from x in source select new { x.Name, x.ID, };

का उपयोग करते हुए

वहाँ के दो प्रकार हैं using , कीवर्ड प्रयोग using statement और using directive :

  1. बयान का उपयोग कर :

    using कीवर्ड यह सुनिश्चित करता है कि उपयोग के बाद IDisposable इंटरफ़ेस को लागू करने वाली वस्तुओं को ठीक से निपटाया जाए। उपयोग कथन के लिए एक अलग विषय है

  2. निर्देशन का उपयोग करना

    using निर्देश के तीन उपयोग हैं, निर्देश का using लिए msdn पृष्ठ देखें। उपयोग करने के निर्देश के लिए एक अलग विषय है।

सील

जब एक वर्ग पर लागू किया जाता है, तो sealed संशोधक अन्य वर्गों को इससे विरासत में मिलने से रोकता है।

class A { }
sealed class B : A { }
class C : B { } //error : Cannot derive from the sealed class

एक के लिए आवेदन किया जब virtual विधि (या आभासी संपत्ति), sealed से संशोधक रोकता है इस विधि (संपत्ति) व्युत्पन्न वर्ग में ओवरराइड जा रहा है।

public class A 
{
    public sealed override string ToString() // Virtual method inherited from class Object
    {
        return "Do not override me!";
    }
}

public class B: A 
{
    public override string ToString() // Compile time error
    { 
        return "An attempt to override"; 
    }
}

इस आकार का

एक अप्रबंधित प्रकार के लिए बाइट्स में आकार प्राप्त करने के लिए उपयोग किया जाता है

int byteSize = sizeof(byte) // 1
int sbyteSize = sizeof(sbyte) // 1
int shortSize = sizeof(short) // 2
int ushortSize = sizeof(ushort) // 2
int intSize = sizeof(int) // 4
int uintSize = sizeof(uint) // 4
int longSize = sizeof(long) // 8
int ulongSize = sizeof(ulong) // 8
int charSize = sizeof(char) // 2(Unicode)
int floatSize = sizeof(float) // 4
int doubleSize = sizeof(double) // 8
int decimalSize = sizeof(decimal) // 16
int boolSize = sizeof(bool) // 1

स्थिर

static संशोधक का उपयोग एक स्थैतिक सदस्य की घोषणा करने के लिए किया जाता है, जिसे एक्सेस करने के लिए तत्काल करने की आवश्यकता नहीं होती है, बल्कि इसके नाम के माध्यम से, यानी DateTime.Now तक पहुँचा जा सकता है।

static का उपयोग कक्षाओं, क्षेत्रों, विधियों, गुणों, ऑपरेटरों, घटनाओं और निर्माणकर्ताओं के साथ किया जा सकता है।

जबकि एक कक्षा की एक आवृत्ति में कक्षा के सभी उदाहरण क्षेत्रों की एक अलग प्रतिलिपि होती है, प्रत्येक स्थिर क्षेत्र की केवल एक प्रतिलिपि होती है।

class A
{
    static public int count = 0;

    public A()
    {
        count++;
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        A b = new A();
        A c = new A();

        Console.WriteLine(A.count); // 3 
    }
}

count A श्रेणी के कुल उदाहरणों के बराबर होती है।

स्थैतिक संशोधक का उपयोग किसी वर्ग के लिए स्थैतिक निर्माणकर्ता की घोषणा करने के लिए भी किया जा सकता है, स्थैतिक डेटा को प्रारंभ करने या कोड चलाने के लिए जिसे केवल एक बार बुलाया जाना चाहिए। क्लास के पहली बार संदर्भित होने से पहले स्टेटिक कंस्ट्रक्टर को बुलाया जाता है।

class A
{
    static public DateTime InitializationTime;

    // Static constructor
    static A()
    {
        InitializationTime = DateTime.Now;
        // Guaranteed to only run once
        Console.WriteLine(InitializationTime.ToString());
    }
}

एक static class को static कीवर्ड के साथ चिह्नित किया जाता है, और इसका उपयोग एक ऐसे कंटेनर के रूप में किया जा सकता है, जो कई मापदंडों पर काम करता है, लेकिन जरूरी नहीं कि इसे एक उदाहरण से जोड़ा जाए। वर्ग की static प्रकृति के कारण, इसे तत्काल नहीं किया जा सकता है, लेकिन इसमें एक static constructorstatic class की कुछ विशेषताओं में शामिल हैं:

  • विरासत में नहीं मिल सकता है
  • Object अलावा किसी अन्य चीज़ से विरासत में नहीं मिल सकता है
  • एक स्थिर कंस्ट्रक्टर हो सकता है लेकिन एक उदाहरण कंस्ट्रक्टर नहीं
  • केवल स्थैतिक सदस्य ही हो सकते हैं
  • सीलबंद है

कंपाइलर भी अनुकूल है और डेवलपर को बताएगा कि क्या कोई उदाहरण सदस्य वर्ग के भीतर मौजूद हैं। एक उदाहरण एक स्थिर वर्ग होगा जो यूएस और कनाडाई मीट्रिक के बीच परिवर्तित होता है:

static class ConversionHelper {
    private static double oneGallonPerLitreRate = 0.264172;

    public static double litreToGallonConversion(int litres) {
        return litres * oneGallonPerLitreRate;
    }
}

जब वर्गों को स्थिर घोषित किया जाता है:

public static class Functions
{
  public static int Double(int value)
  {
    return value + value;
  }
}

सभी फ़ंक्शन, गुण या वर्ग के सदस्यों को भी स्थिर घोषित करने की आवश्यकता है। वर्ग का कोई उदाहरण नहीं बनाया जा सकता है। संक्षेप में एक स्थिर वर्ग आपको उन कार्यों के बंडलों को बनाने की अनुमति देता है जो तार्किक रूप से एक साथ समूहीकृत होते हैं।

चूंकि C # 6 static using स्टैटिक सदस्यों और विधियों को आयात करने के लिए भी किया जा सकता है। उनका उपयोग तब वर्ग नाम के बिना किया जा सकता है।

पुराने तरीके, using static किए बिना:

using System;

public class ConsoleApplication
{
    public static void Main()
    {
         Console.WriteLine("Hello World!"); //Writeline is method belonging to static class Console
    }

}

using static साथ उदाहरण

using static System.Console;

public class ConsoleApplication
{
    public static void Main()
    {
         WriteLine("Hello World!"); //Writeline is method belonging to static class Console
    }

}

कमियां

जबकि स्थैतिक वर्ग अविश्वसनीय रूप से उपयोगी हो सकते हैं, वे अपने स्वयं के कैविएट के साथ आते हैं:

  • एक बार स्थिर वर्ग को बुलाए जाने के बाद, कक्षा को मेमोरी में लोड कर दिया जाता है और कचरा संग्रहकर्ता के माध्यम से नहीं चलाया जा सकता है जब तक कि AppDomain आवास स्थिर क्लास अनलोड नहीं हो जाता है।

  • एक स्थिर वर्ग एक इंटरफ़ेस लागू नहीं कर सकता है।

पूर्णांक

int System.Int32 लिए एक उपनाम है, जो हस्ताक्षरित 32-बिट पूर्णांक के लिए एक डेटा प्रकार है। यह डेटा प्रकार mscorlib.dll में पाया जा सकता है जो कि प्रत्येक C # प्रोजेक्ट द्वारा स्पष्ट रूप से संदर्भित होता है जब आप उन्हें बनाते हैं।

रेंज: -2,147,483,648 से 2,147,483,647

int int1 = -10007;
var int2 = 2132012521;     

लंबा

लंबे कीवर्ड का उपयोग हस्ताक्षरित 64-बिट पूर्णांक का प्रतिनिधित्व करने के लिए किया जाता है। यह mscorlib.dll में मौजूद System.Int64 डेटाटाइप के लिए एक अन्य नाम है, जिसे आप बनाते समय प्रत्येक C # प्रोजेक्ट द्वारा संदर्भित किया जाता है।

किसी भी लंबे चर को स्पष्ट और निहित रूप से घोषित किया जा सकता है:

long long1 = 9223372036854775806;  // explicit declaration, long keyword used
var long2 = -9223372036854775806L; // implicit declaration, 'L' suffix used

एक लंबा वैरिएबल किसी भी मान को -9,223,372,036,854,775,808 से 9,223,372,036,854,775,807 तक पकड़ सकता है, और ऐसी परिस्थितियों में उपयोगी हो सकता है, जो एक वैरिएबल का मान रखने के लिए दूसरे वेरिएबल (जैसे इंट वैरिएबल) की सीमा से अधिक हो।

Ulong

अनिर्दिष्ट 64-बिट पूर्णांक के लिए उपयोग किया जाने वाला कीवर्ड। यह प्रतिनिधित्व करता System.UInt64 में पाया डेटा प्रकार mscorlib.dll जो परोक्ष हर सी # परियोजना द्वारा संदर्भित है जब आपने उन्हें बनाया।

रेंज: 0 से 18,446,744,073,709,551,615

ulong veryLargeInt = 18446744073609451315;
var anotherVeryLargeInt = 15446744063609451315UL;

गतिशील

dynamic कीवर्ड का उपयोग डायनामिक रूप से टाइप की गई वस्तुओं के साथ किया जाता है। ऑब्जेक्ट्स को dynamic फोरगो कंपाइल-टाइम स्टैटिक चेक के रूप में घोषित किया गया है, और इसके बजाय रनटाइम पर मूल्यांकन किया जाता है।

using System;
using System.Dynamic;

dynamic info = new ExpandoObject();
info.Id = 123;
info.Another = 456;

Console.WriteLine(info.Another);
// 456

Console.WriteLine(info.DoesntExist);
// Throws RuntimeBinderException

निम्न उदाहरण न्यूटनसॉफ्ट की लाइब्रेरी Json.NET के साथ dynamic का उपयोग करता है, ताकि आसानी से एक deserialized JSON फ़ाइल से डेटा पढ़ा जा सके।

try
{
    string json = @"{ x : 10, y : ""ho""}";
    dynamic deserializedJson = JsonConvert.DeserializeObject(json);
    int x = deserializedJson.x;
    string y = deserializedJson.y;
    // int z = deserializedJson.z; // throws RuntimeBinderException
}
catch (RuntimeBinderException e)
{
    // This exception is thrown when a property
    // that wasn't assigned to a dynamic variable is used
}

डायनामिक कीवर्ड से जुड़ी कुछ सीमाएँ हैं। उनमें से एक विस्तार विधियों का उपयोग है। निम्न उदाहरण स्ट्रिंग के लिए एक एक्सटेंशन विधि जोड़ता है: SayHello

static class StringExtensions
{
    public static string SayHello(this string s) => $"Hello {s}!";
}

पहला तरीका यह होगा कि आप इसे हमेशा की तरह (स्ट्रिंग के लिए) कहें:

var person = "Person";
Console.WriteLine(person.SayHello());

dynamic manager = "Manager";
Console.WriteLine(manager.SayHello()); // RuntimeBinderException

कोई संकलन त्रुटि नहीं है, लेकिन रनटाइम पर आपको एक RuntimeBinderException । इसके लिए समाधान स्टैटिक क्लास के माध्यम से विस्तार विधि को कॉल करना होगा:

var helloManager = StringExtensions.SayHello(manager);
Console.WriteLine(helloManager);

वर्चुअल, ओवरराइड, नया

आभासी और ओवरराइड

virtual कीवर्ड एक विधि, संपत्ति, अनुक्रमणिका या घटना को व्युत्पन्न वर्गों और वर्तमान बहुरूपी व्यवहार से अतिरंजित होने की अनुमति देता है। (सदस्य C # में डिफ़ॉल्ट रूप से गैर-आभासी हैं)

public class BaseClass
{
    public virtual void Foo()
    {
        Console.WriteLine("Foo from BaseClass");
    }
}

किसी सदस्य को ओवरराइड करने के लिए, override कीवर्ड का उपयोग व्युत्पन्न वर्गों में किया जाता है। (नोट सदस्यों के हस्ताक्षर समान होना चाहिए)

public class DerivedClass: BaseClass
{
    public override void Foo()
    {
        Console.WriteLine("Foo from DerivedClass");
    }
}

आभासी सदस्यों के बहुरूपी व्यवहार का अर्थ है कि जब आह्वान किया जाता है, तो निष्पादित किए जाने वाले वास्तविक सदस्य को निर्धारित समय के बजाय रनटाइम पर निर्धारित किया जाता है। सबसे अधिक व्युत्पन्न वर्ग में ओवरराइडिंग सदस्य विशेष वस्तु एक उदाहरण है जिसे निष्पादित किया जाएगा।

संक्षेप में, ऑब्जेक्ट प्रकार का घोषित किया जा सकता BaseClass संकलन समय पर, लेकिन अगर रनटाइम पर यह का एक उदाहरण है DerivedClass तो ओवरराइड सदस्य निष्पादित किया जाएगा:

BaseClass obj1 = new BaseClass();
obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();
obj1.Foo(); //Outputs "Foo from DerivedClass"    

एक विधि को ओवरराइड करना वैकल्पिक है:

public class SecondDerivedClass: DerivedClass {}

var obj1 = new SecondDerivedClass();
obj1.Foo(); //Outputs "Foo from DerivedClass"    

नया

चूँकि केवल virtual रूप में परिभाषित किए गए सदस्य अति-योग्य और बहुरूपी हैं, इसलिए एक गैर-आभासी सदस्य को पुनर्परिभाषित करने वाला एक वर्ग अप्रत्याशित परिणाम ला सकता है।

public class BaseClass
{
    public void Foo()
    {
        Console.WriteLine("Foo from BaseClass");
    }
}

public class DerivedClass: BaseClass
{
    public void Foo()
    {
        Console.WriteLine("Foo from DerivedClass");
    }
}

BaseClass obj1 = new BaseClass();
obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();
obj1.Foo(); //Outputs "Foo from BaseClass" too!    

जब ऐसा होता है, तो निष्पादित सदस्य हमेशा वस्तु के प्रकार के आधार पर संकलन समय पर निर्धारित किया जाता है।

  • यदि ऑब्जेक्ट BaseClass के प्रकार से घोषित होता है (भले ही रनटाइम एक व्युत्पन्न वर्ग का हो) तो BaseClass की विधि निष्पादित की जाती है
  • यदि ऑब्जेक्ट को DerivedClass घोषित किया जाता है तो DerivedClass की विधि निष्पादित की DerivedClass है।

यह आमतौर पर एक दुर्घटना है (जब एक सदस्य को आधार प्रकार में जोड़ा जाता है एक समान एक के बाद एक व्युत्पन्न प्रकार में जोड़ा गया था) और एक संकलक चेतावनी CS0108 उन परिदृश्यों में उत्पन्न होता है।

यदि यह जानबूझकर किया गया था, तो new कीवर्ड का उपयोग कंपाइलर चेतावनी को दबाने के लिए किया जाता है (और आपके इरादों के अन्य डेवलपर्स को सूचित करें!)। व्यवहार वही रहता है, new कीवर्ड बस संकलक चेतावनी को दबा देता है।

public class BaseClass
{
    public void Foo()
    {
        Console.WriteLine("Foo from BaseClass");
    }
}

public class DerivedClass: BaseClass
{
    public new void Foo()
    {
        Console.WriteLine("Foo from DerivedClass");
    }
}

BaseClass obj1 = new BaseClass();
obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();
obj1.Foo(); //Outputs "Foo from BaseClass" too! 

ओवरराइड का उपयोग वैकल्पिक नहीं है

C ++ के विपरीत, override कीवर्ड का उपयोग वैकल्पिक नहीं है :

public class A
{
    public virtual void Foo()
    {
    }
}

public class B : A
{
    public void Foo() // Generates CS0108
    {
    }
}

उपरोक्त उदाहरण भी CS0108 को चेतावनी देता है , क्योंकि B.Foo() स्वचालित रूप से A.Foo() ओवरराइड नहीं कर रहा है। जोड़े override जब इसका उद्देश्य, आधार वर्ग को ओवरराइड और बहुरूपी व्यवहार का कारण करने के लिए जोड़ है new जब आप गैर बहुरूपी व्यवहार चाहते हैं और कॉल स्थिर प्रकार का उपयोग कर हल। उत्तरार्द्ध को सावधानी के साथ इस्तेमाल किया जाना चाहिए, क्योंकि इससे गंभीर भ्रम हो सकता है।

निम्न कोड में भी त्रुटि होती है:

public class A
{
    public void Foo()
    {
    }
}

public class B : A
{
    public override void Foo() // Error: Nothing to override
    {
    }
}

व्युत्पन्न वर्ग बहुरूपता का परिचय दे सकते हैं

निम्नलिखित कोड पूरी तरह से वैध है (हालांकि दुर्लभ):

    public class A
    {
        public void Foo()
        {
            Console.WriteLine("A");
        }
    }

    public class B : A
    {
        public new virtual void Foo() 
        {
            Console.WriteLine("B");
        }
    }

अब B (और उसके डेरिवेटिव) के एक स्थिर संदर्भ वाली सभी वस्तुएं Foo() को हल करने के लिए बहुरूपता का उपयोग करती हैं, जबकि A उपयोग के संदर्भ A.Foo()

A a = new A();
a.Foo(); // Prints "A";
a = new B();
a.Foo(); // Prints "A";
B b = new B();
b.Foo(); // Prints "B";

वर्चुअल तरीके निजी नहीं हो सकते

C # संकलक संवेदनाहीन निर्माण को रोकने में सख्त है। virtual के रूप में चिह्नित तरीके निजी नहीं हो सकते। क्योंकि एक निजी पद्धति को एक व्युत्पन्न प्रकार से नहीं देखा जा सकता है, इसे या तो ओवरराइट नहीं किया जा सकता है। यह संकलन करने में विफल रहता है:

public class A
{
    private virtual void Foo() // Error: virtual methods cannot be private
    {
    }
}

async, प्रतीक्षा करें

await कीवर्ड को C # 5.0 रिलीज के भाग के रूप में जोड़ा गया था, जो विजुअल स्टूडियो 2012 के बाद से समर्थित है। यह टास्क पैरेलल लाइब्रेरी (TPL) का लाभ उठाता है जिसने बहु-थ्रेडिंग को अपेक्षाकृत आसान बना दिया है। नीचे दिए गए async और await कीवर्ड का उपयोग जोड़े में किया जाता है। await कीवर्ड को वर्तमान अतुल्यकालिक विधि के निष्पादन को रोकने के लिए उपयोग किया जाता है जब तक कि प्रतीक्षित अतुल्यकालिक कार्य पूरा नहीं होता है और / या इसके परिणाम वापस आ जाते हैं। await कीवर्ड का उपयोग करने के लिए, इसका उपयोग करने वाली विधि को async कीवर्ड के साथ चिह्नित किया जाना चाहिए।

void साथ async का उपयोग दृढ़ता से हतोत्साहित किया जाता है। अधिक जानकारी के लिए आप यहां देख सकते हैं

उदाहरण:

public async Task DoSomethingAsync()
{    
    Console.WriteLine("Starting a useless process...");
    Stopwatch stopwatch = Stopwatch.StartNew();
    int delay = await UselessProcessAsync(1000);
    stopwatch.Stop();
    Console.WriteLine("A useless process took {0} milliseconds to execute.", stopwatch.ElapsedMilliseconds);
}

public async Task<int> UselessProcessAsync(int x)
{
    await Task.Delay(x);
    return x;
}

आउटपुट:

"एक बेकार प्रक्रिया शुरू ..."

** ... 1 सेकंड की देरी ... **

"एक बेकार प्रक्रिया को निष्पादित करने के लिए 1000 मिलीसेकंड लिया गया।"

यदि कोई Task या Task<T> रिटर्निंग विधि केवल एक एसिंक्रोनस ऑपरेशन लौटाता है, तो async और await जोड़े को छोड़ दिया जा सकता है।

इसके बजाय:

public async Task PrintAndDelayAsync(string message, int delay)
{
    Debug.WriteLine(message);
    await Task.Delay(x);
}

यह करना पसंद किया जाता है:

public Task PrintAndDelayAsync(string message, int delay)
{
    Debug.WriteLine(message);
    return Task.Delay(x);
}
5.0

C # 5.0 await में catch और finally में उपयोग नहीं किया जा सकता है।

6.0

C # 6.0 के साथ वेट await उपयोग catch और finally में किया जा सकता है।

चार

एक चर एक पत्र एक चर के अंदर संग्रहीत है। यह बिल्ट-इन मूल्य प्रकार है जो मेमोरी स्पेस के दो बाइट्स लेता है। यह प्रतिनिधित्व करता System.Char में पाया डेटा प्रकार mscorlib.dll जो परोक्ष हर सी # परियोजना द्वारा संदर्भित है जब आपने उन्हें बनाया।

ऐसा करने के कई तरीके हैं।

  1. char c = 'c';
  2. char c = '\u0063'; //Unicode
  3. char c = '\x0063'; //Hex
  4. char c = (char)99;//Integral

एक वर्ण को ushort, int, uint, long, ulong, float, double, या decimal बदला जा सकता है और यह उस char के पूर्णांक मान को लौटा देगा।

ushort u = c;

रिटर्न 99 आदि।

हालांकि, अन्य प्रकारों से चार में कोई अंतर्निहित रूपांतरण नहीं हैं। इसके बजाय आपको उन्हें कास्ट करना होगा।

ushort u = 99;
 char c = (char)u;

ताला

lock कोड के ब्लॉक के लिए थ्रेड-सुरक्षा प्रदान करता है, ताकि इसे उसी प्रक्रिया के भीतर केवल एक थ्रेड द्वारा पहुँचा जा सके। उदाहरण:

private static object _lockObj = new object();
static void Main(string[] args)
{
    Task.Run(() => TaskWork());
    Task.Run(() => TaskWork());
    Task.Run(() => TaskWork());

    Console.ReadKey();
}

private static void TaskWork()
{
    lock(_lockObj)
    {
        Console.WriteLine("Entered");

        Task.Delay(3000);
        Console.WriteLine("Done Delaying");

        // Access shared resources safely

        Console.WriteLine("Leaving");
    }   
}

Output:

Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving

बक्सों का इस्तेमाल करें:

जब भी आपके पास कोड का एक ब्लॉक होता है जो एक ही समय में कई थ्रेड्स द्वारा निष्पादित होने पर साइड-इफेक्ट्स उत्पन्न कर सकता है। एक साझा सिंक्रनाइज़ेशन ऑब्जेक्ट (उदाहरण में _objLock ) के साथ लॉक कीवर्ड का उपयोग इसे रोकने के लिए किया जा सकता है।

ध्यान दें कि _objLock null नहीं हो सकता है और कोड को निष्पादित करने वाले कई थ्रेड्स एक ही ऑब्जेक्ट इंस्टेंस का उपयोग करना चाहिए (या तो इसे एक static फ़ील्ड बनाकर, या दोनों थ्रेड्स के लिए एक ही क्लास इंस्टेंस का उपयोग करके)

कंपाइलर की तरफ से, लॉक कीवर्ड एक सिंटैक्टिक शुगर है जिसे Monitor.Enter(_lockObj); द्वारा प्रतिस्थापित किया जाता है Monitor.Enter(_lockObj); और Monitor.Exit(_lockObj); । इसलिए यदि आप इन दोनों विधियों के साथ कोड के ब्लॉक को घेरकर लॉक को बदलते हैं, तो आपको समान परिणाम प्राप्त होंगे। आप C # - लॉक उदाहरण में Syntactic चीनी में वास्तविक कोड देख सकते हैं

शून्य

एक संदर्भ प्रकार का एक चर या तो एक उदाहरण या शून्य संदर्भ के लिए एक वैध संदर्भ धारण कर सकता है। अशक्त संदर्भ संदर्भ प्रकार चर का डिफ़ॉल्ट मान है, साथ ही अशक्त मूल्य प्रकार भी है।

null वह कीवर्ड है जो null संदर्भ का प्रतिनिधित्व करता है।

एक अभिव्यक्ति के रूप में, इसका उपयोग उपरोक्त प्रकार के चर के अशक्त संदर्भ को निर्दिष्ट करने के लिए किया जा सकता है:

object a = null;
string b = null;
int? c = null;
List<int> d  = null;

गैर-अशक्त मान प्रकारों को अशक्त संदर्भ नहीं दिया जा सकता है। निम्नलिखित सभी कार्य अमान्य हैं:

int a = null; 
float b = null;
decimal c = null;

अशक्त संदर्भ को विभिन्न प्रकारों के मान्य उदाहरणों के साथ भ्रमित नहीं होना चाहिए:

  • एक खाली सूची ( new List<int>() )
  • एक खाली स्ट्रिंग ( "" )
  • संख्या शून्य ( 0 , 0f , 0m )
  • अशक्त चरित्र ( '\0' )

कभी-कभी, यह जाँचना सार्थक होता है कि कोई चीज़ अशक्त है या रिक्त / डिफ़ॉल्ट वस्तु। यह जाँचने के लिए System.String.IsNullOrEmpty (स्ट्रिंग) विधि का उपयोग किया जा सकता है, या आप अपने स्वयं के समकक्ष पद्धति को लागू कर सकते हैं।

private void GreetUser(string userName)
{
    if (String.IsNullOrEmpty(userName))
    {
        //The method that called us either sent in an empty string, or they sent us a null reference. Either way, we need to report the problem.
        throw new InvalidOperationException("userName may not be null or empty.");
    }
    else
    {
        //userName is acceptable.
        Console.WriteLine("Hello, " + userName + "!");
    }
}

अंदर का

internal कीवर्ड प्रकारों और प्रकार के सदस्यों के लिए एक पहुंच संशोधक है। आंतरिक प्रकार या सदस्य केवल एक ही विधानसभा में फ़ाइलों के भीतर पहुंच योग्य हैं

उपयोग:

public class BaseClass 
{
    // Only accessible within the same assembly
    internal static int x = 0;
}

विभिन्न पहुँच संशोधक के बीच का अंतर यहाँ स्पष्ट किया गया है

पहुँच संशोधक

जनता

प्रकार या सदस्य को उसी विधानसभा या किसी अन्य विधानसभा में किसी अन्य कोड द्वारा एक्सेस किया जा सकता है जो इसे संदर्भित करता है।

निजी

प्रकार या सदस्य को केवल उसी कक्षा या संरचना में कोड द्वारा पहुँचा जा सकता है।

संरक्षित

प्रकार या सदस्य को केवल उसी वर्ग या संरचना में या एक व्युत्पन्न वर्ग में कोड द्वारा पहुँचा जा सकता है।

अंदर का

प्रकार या सदस्य को उसी विधानसभा में किसी भी कोड द्वारा पहुँचा जा सकता है, लेकिन किसी अन्य विधानसभा से नहीं।

संरक्षित आंतरिक

प्रकार या सदस्य को उसी विधानसभा में किसी भी कोड या किसी अन्य विधानसभा में किसी भी व्युत्पन्न वर्ग द्वारा पहुँचा जा सकता है।

जब कोई एक्सेस संशोधक सेट नहीं किया जाता है, तो डिफ़ॉल्ट एक्सेस संशोधक का उपयोग किया जाता है। तो वहाँ हमेशा पहुँच संशोधक के कुछ फार्म है भले ही यह सेट नहीं है।

कहाँ पे

where C # में दो उद्देश्य दिए जा सकते हैं: एक सामान्य तर्क में कसना, और LINQ प्रश्नों को फ़िल्टर करना।

एक सामान्य वर्ग में, आइए विचार करें

public class Cup<T>
{
    // ...
}

T को एक प्रकार का पैरामीटर कहा जाता है। वर्ग परिभाषा टी के लिए आपूर्ति की जा सकने वाले वास्तविक प्रकारों पर अवरोध लगा सकती है।

निम्नलिखित प्रकार की बाधाओं को लागू किया जा सकता है:

  • मान प्रकार
  • संदर्भ प्रकार
  • डिफ़ॉल्ट निर्माता
  • विरासत और कार्यान्वयन

मान प्रकार

इस मामले में केवल struct एस (इसमें 'आदिम' डेटा प्रकार जैसे कि int , boolean आदि) की आपूर्ति की जा सकती है

public class Cup<T> where T : struct
{
    // ...
}

संदर्भ प्रकार

इस मामले में केवल वर्ग प्रकार की आपूर्ति की जा सकती है

public class Cup<T> where T : class
{
    // ...
}

संकर मान / संदर्भ प्रकार

कभी-कभी यह डेटाबेस में उपलब्ध लोगों के लिए प्रकार के तर्कों को प्रतिबंधित करने के लिए वांछित होता है, और ये आमतौर पर प्रकारों और तारों को महत्व देते हैं। जैसा कि सभी प्रकार के प्रतिबंधों को पूरा किया जाना चाहिए, यह निर्दिष्ट करना संभव नहीं है where T : struct or string (यह मान्य सिंटैक्स नहीं है)। एक वर्कअराउंड प्रकार के तर्कों को IConvertible तक सीमित करने के लिए है जो "... बूलियन, SByte, बाइट, Int16, UInt16, Int32, UInt32, Int64, UInt64, सिंगल, डबल, दशमलव, डेटाइम, चार और स्ट्रिंग में टाइप किया है। " यह संभव है कि अन्य वस्तुएं IConvertible को लागू करें, हालांकि यह व्यवहार में दुर्लभ है।

public class Cup<T> where T : IConvertible
{
    // ...
}

डिफ़ॉल्ट निर्माता

केवल उन्हीं प्रकारों को शामिल किया गया है जिनमें एक डिफ़ॉल्ट निर्माता होता है। इसमें मूल्य प्रकार और कक्षाएं शामिल हैं जिनमें एक डिफ़ॉल्ट (पैरामीटर रहित) कंस्ट्रक्टर है

public class Cup<T> where T : new
{
    // ...
}

विरासत और कार्यान्वयन

केवल प्रकार जो एक निश्चित आधार वर्ग से विरासत में मिलते हैं या एक निश्चित इंटरफ़ेस को लागू करते हैं, आपूर्ति की जा सकती है।

public class Cup<T> where T : Beverage
{
    // ...
}


public class Cup<T> where T : IBeer
{
    // ...
}

बाधा एक अन्य प्रकार के पैरामीटर को भी संदर्भित कर सकती है:

public class Cup<T, U> where U : T
{
    // ...
}

एक प्रकार के तर्क के लिए कई बाधाओं को निर्दिष्ट किया जा सकता है:

public class Cup<T> where T : class, new()
{
    // ...
}

पिछले उदाहरण एक वर्ग परिभाषा पर सामान्य बाधाओं को दर्शाते हैं, लेकिन बाधाओं का उपयोग कहीं भी किया जा सकता है एक प्रकार का तर्क दिया जाता है: वर्ग, संरचना, इंटरफेस, विधियाँ, आदि।

where एक LINQ क्लॉज भी हो सकता है। इस स्थिति में यह SQL में WHERE अनुरूप है:

int[] nums = { 5, 2, 1, 3, 9, 8, 6, 7, 2, 0 };

var query =
    from num in nums 
    where num < 5
    select num;

    foreach (var n in query)
    {
        Console.Write(n + " ");
    }
    // prints 2 1 3 2 0

निर्वासन

extern कीवर्ड तरीकों कि बाहर से लागू किया जाता है की घोषणा करने के लिए किया जाता है। यह इंटरोप सेवाओं का उपयोग करते हुए अप्रबंधित कोड में कॉल करने के लिए DllImport विशेषता के साथ संयोजन में उपयोग किया जा सकता है। जो इस मामले में यह static संशोधक के साथ आएगा

उदाहरण के लिए:

using System.Runtime.InteropServices;
public class MyClass
{
    [DllImport("User32.dll")]
    private static extern int SetForegroundWindow(IntPtr point);

    public void ActivateProcessWindow(Process p)
    {
        SetForegroundWindow(p.MainWindowHandle);
    }
}

यह User32.dll लायब्रेरी से आयातित SetForegroundWindow विधि का उपयोग करता है

इसका उपयोग बाहरी विधानसभा उपनाम को परिभाषित करने के लिए भी किया जा सकता है। जो हमें एक ही विधानसभा से एक ही घटक के विभिन्न संस्करणों को संदर्भित करने की अनुमति देते हैं।

एक ही पूरी तरह से योग्य प्रकार के नाम के साथ दो विधानसभाओं को संदर्भित करने के लिए, एक उपनाम को कमांड प्रॉम्प्ट पर निर्दिष्ट किया जाना चाहिए, निम्नानुसार:

/r:GridV1=grid.dll
/r:GridV2=grid20.dll

यह बाहरी उपनाम GridV1 और GridV2 बनाता है। एक कार्यक्रम के भीतर से इन उपनामों का उपयोग करने के लिए, बाहरी कीवर्ड का उपयोग करके उन्हें देखें। उदाहरण के लिए:

extern alias GridV1;
extern alias GridV2;

bool

बूलियन मूल्यों को true और false संग्रहीत करने के लिए कीवर्ड। बूल सिस्टम का एक उपनाम है। बूलियन।

एक बूल का डिफ़ॉल्ट मान गलत है।

bool b; // default value is false
b = true; // true
b = ((5 + 2) == 6); // false

एक बूल के लिए अशक्त मूल्यों की अनुमति देने के लिए इसे एक बूल के रूप में आरंभीकृत किया जाना चाहिए?

एक बूल का डिफ़ॉल्ट मान? शून्य है।

bool? a // default value is null

कब

when कोई कीवर्ड C # 6 में जोड़ा जाता है , और इसका उपयोग अपवाद फ़िल्टरिंग के लिए किया जाता है।

when कीवर्ड की शुरुआत से पहले, आप प्रत्येक प्रकार के अपवाद के लिए एक पकड़ क्लॉज हो सकते थे; कीवर्ड के अतिरिक्त के साथ, एक अधिक बारीक नियंत्रण अब संभव है।

when अभिव्यक्ति को catch शाखा से जोड़ा जाता है, और केवल when स्थिति true होती true , तो catch क्लॉज़ निष्पादित किया जाएगा। एक ही अपवाद वर्ग प्रकारों के साथ कई catch क्लॉज होना संभव है, और when स्थितियां अलग when हैं।

private void CatchException(Action action)
{
    try
    {
        action.Invoke();
    }
    
    // exception filter
    catch (Exception ex) when (ex.Message.Contains("when"))
    {
        Console.WriteLine("Caught an exception with when");
    }

    catch (Exception ex)
    {
        Console.WriteLine("Caught an exception without when");
    }
}

private void Method1() { throw new Exception("message for exception with when"); }
private void Method2() { throw new Exception("message for general exception"); }


CatchException(Method1);
CatchException(Method2);

अनियंत्रित

unchecked कीवर्ड कंपाइलर को ओवरफ्लो / अंडरफ्लो की जांच करने से रोकता है।

उदाहरण के लिए:

const int ConstantMax = int.MaxValue;
unchecked
{
    int1 = 2147483647 + 10;
}
int1 = unchecked(ConstantMax + 10);

unchecked कीवर्ड के बिना, दो जोड़ आपरेशनों में से कोई भी संकलन नहीं करेगा।

यह कब उपयोगी है?

यह उपयोगी है क्योंकि यह गणनाओं को गति देने में मदद कर सकता है जो निश्चित रूप से अतिप्रवाह नहीं करेगा क्योंकि अतिप्रवाह के लिए जाँच करने में समय लगता है, या जब एक अतिप्रवाह / अंतर्प्रवाह वांछित व्यवहार होता है (उदाहरण के लिए, हैश कोड बनाते समय)।

शून्य

आरक्षित शब्द "void" System.Void प्रकार का एक उपनाम है, और इसके दो उपयोग हैं:

  1. एक ऐसी विधि घोषित करें जिसमें रिटर्न वैल्यू न हो:
public void DoSomething()
{
    // Do some work, don't return any value to the caller.
}

एक प्रकार की वापसी के साथ एक विधि अभी भी अपने शरीर में return कीवर्ड रख सकती है। यह उपयोगी है जब आप विधि के निष्पादन से बाहर निकलना चाहते हैं और फोन करने वाले को प्रवाह लौटना चाहते हैं:

public void DoSomething()
{
    // Do some work...

    if (condition)
        return;

    // Do some more work if the condition evaluated to false.
}
  1. असुरक्षित संदर्भ में एक अज्ञात प्रकार के लिए एक संकेतक घोषित करें।

असुरक्षित संदर्भ में, एक प्रकार एक सूचक प्रकार, एक मान प्रकार या एक संदर्भ प्रकार हो सकता है। एक सूचक प्रकार की घोषणा आमतौर पर type* identifier , जहां प्रकार एक ज्ञात प्रकार है - यानी int* myInt , लेकिन void* identifier भी हो सकता है, जहां प्रकार अज्ञात है।

ध्यान दें कि शून्य पॉइंटर प्रकार की घोषणा करना Microsoft द्वारा हतोत्साहित किया जाता है।

यदि, यदि ... और, यदि ... और यदि


if कथन का उपयोग कार्यक्रम के प्रवाह को नियंत्रित करने के लिए किया जाता है। if एक कथन Boolean अभिव्यक्ति के मूल्य के आधार पर कौन से कथन को चलाता है, की पहचान करता है।

एकल कथन के लिए, braces {} वैकल्पिक हैं, लेकिन अनुशंसित हैं।

int a = 4;
if(a % 2 == 0) 
{
     Console.WriteLine("a contains an even number");
}
// output: "a contains an even number"

if कोई else खंड भी हो सकता है, तो उस स्थिति में निष्पादित किया जाएगा जब स्थिति गलत का मूल्यांकन करती है:

int a = 5;
if(a % 2 == 0) 
{
     Console.WriteLine("a contains an even number");
}
else
{
     Console.WriteLine("a contains an odd number");
}
// output: "a contains an odd number"

if ... else if निर्माण आपको कई शर्तें निर्दिष्ट करने देता है:

int a = 9;
if(a % 2 == 0) 
{
     Console.WriteLine("a contains an even number");
}
else if(a % 3 == 0) 
{
     Console.WriteLine("a contains an odd number that is a multiple of 3"); 
}
else
{
     Console.WriteLine("a contains an odd number");
}
// output: "a contains an odd number that is a multiple of 3"

यह ध्यान रखना महत्वपूर्ण है कि यदि उपरोक्त उदाहरण में कोई शर्त पूरी की जाती है, तो नियंत्रण अन्य परीक्षणों को छोड़ देता है और उस विशेष के अंत में कूद जाता है यदि निर्माण होता है। तो, यदि आप उपयोग कर रहे हैं तो परीक्षणों का क्रम महत्वपूर्ण है।

C # बूलियन अभिव्यक्ति शॉर्ट-सर्किट मूल्यांकन का उपयोग करती है। यह उन मामलों में महत्वपूर्ण है, जहां मूल्यांकन स्थितियों का दुष्प्रभाव हो सकता है:

if (someBooleanMethodWithSideEffects() && someOtherBooleanMethodWithSideEffects()) {
  //...
}

कोई गारंटी नहीं है कि someOtherBooleanMethodWithSideEffects वास्तव में चलेगा।

यह उन मामलों में भी महत्वपूर्ण है जहां पहले की स्थिति यह सुनिश्चित करती है कि बाद के लोगों का मूल्यांकन करना "सुरक्षित" है। उदाहरण के लिए:

if (someCollection != null && someCollection.Count > 0) {
   // ..
}

इस मामले में आदेश बहुत महत्वपूर्ण है, क्योंकि यदि हम आदेश को उल्टा करते हैं:

if (someCollection.Count > 0 && someCollection != null) {

यह एक फेंक होगा NullReferenceException अगर someCollection है null

कर

जब तक कोई सशर्त क्वेरी झूठे के बराबर न हो, ऑपरेटर ऑपरेटर कोड के ब्लॉक पर पुनरावृति करता है। डू-जबकि लूप को एक goto , return , break या throw स्टेटमेंट द्वारा भी बाधित किया जा सकता है।

वाक्य विन्यास do कीवर्ड है:

do { कोड ब्लॉक; } जबकि ( स्थिति );

उदाहरण:

int i = 0;

do
{
    Console.WriteLine("Do is on loop number {0}.", i);
} while (i++ < 5);

आउटपुट:

"लूप नंबर 1 पर है"
"लूप नंबर 2 पर है।"
"लूप नंबर 3 पर है"
"Do is on loop number 4."
"लूप नंबर 5 पर है"

विपरीत while पाश, क्या जबकि पाश से बाहर निकलें नियंत्रित किया जाता है। इसका मतलब यह है कि डू-लूप अपने बयानों को कम से कम एक बार निष्पादित करेगा, भले ही स्थिति पहली बार विफल हो।

bool a = false;

do
{
    Console.WriteLine("This will be printed once, even if a is false.");
} while (a == true);

ऑपरेटर

अधिकांश बिल्ट-इन ऑपरेटरों (रूपांतरण ऑपरेटरों सहित) को public और static संशोधक के साथ operator कीवर्ड का उपयोग करके ओवरलोड किया जा सकता है।

ऑपरेटर तीन रूपों में आते हैं: एकरी ऑपरेटर, बाइनरी ऑपरेटर और रूपांतरण ऑपरेटर।

Unary और बाइनरी ऑपरेटरों को कम से कम एक पैरामीटर की आवश्यकता होती है जिसमें शामिल प्रकार होते हैं, और कुछ को एक पूरक मिलान ऑपरेटर की आवश्यकता होती है।

रूपांतरण ऑपरेटरों को एन्क्लोज़िंग प्रकार से या उससे परिवर्तित करना होगा।

public struct Vector32
{
    
    public Vector32(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    public int X { get; }
    public int Y { get; }

    public static bool operator ==(Vector32 left, Vector32 right)
        => left.X == right.X && left.Y == right.Y;

    public static bool operator !=(Vector32 left, Vector32 right)
        => !(left == right);

    public static Vector32 operator +(Vector32 left, Vector32 right)
        => new Vector32(left.X + right.X, left.Y + right.Y);

    public static Vector32 operator +(Vector32 left, int right)
        => new Vector32(left.X + right, left.Y + right);

    public static Vector32 operator +(int left, Vector32 right)
        => right + left;

    public static Vector32 operator -(Vector32 left, Vector32 right)
        => new Vector32(left.X - right.X, left.Y - right.Y);

    public static Vector32 operator -(Vector32 left, int right)
        => new Vector32(left.X - right, left.Y - right);

    public static Vector32 operator -(int left, Vector32 right)
        => right - left;

    public static implicit operator Vector64(Vector32 vector)
        => new Vector64(vector.X, vector.Y);

    public override string ToString() => $"{{{X}, {Y}}}";

}

public struct Vector64
{

    public Vector64(long x, long y)
    {
        X = x;
        Y = y;
    }

    public long X { get; }
    public long Y { get; }

    public override string ToString() => $"{{{X}, {Y}}}";

}

उदाहरण

var vector1 = new Vector32(15, 39);
var vector2 = new Vector32(87, 64);
        
Console.WriteLine(vector1 == vector2); // false
Console.WriteLine(vector1 != vector2); // true
Console.WriteLine(vector1 + vector2);  // {102, 103}
Console.WriteLine(vector1 - vector2);  // {-72, -25}

struct

एक struct प्रकार एक मूल्य प्रकार है जो आम तौर पर संबंधित चर के छोटे समूहों को एन्कैप करने के लिए उपयोग किया जाता है, जैसे कि एक आयत के निर्देशांक या एक सूची में किसी आइटम की विशेषताओं।

कक्षाएं संदर्भ प्रकार हैं, संरचना मूल्य प्रकार हैं।

using static System.Console;

namespace ConsoleApplication1
{
    struct Point
    {
        public int X;
        public int Y;

        public override string ToString()
        {
            return $"X = {X}, Y = {Y}";
        }

        public void Display(string name)
        {
            WriteLine(name + ": " + ToString());
        }
    }

    class Program
    {
        static void Main()
        {
            var point1 = new Point {X = 10, Y = 20};
            // it's not a reference but value type
            var point2 = point1;
            point2.X = 777;
            point2.Y = 888;
            point1.Display(nameof(point1)); // point1: X = 10, Y = 20
            point2.Display(nameof(point2)); // point2: X = 777, Y = 888

            ReadKey();
        }
    }
}

संरचना में कंस्ट्रक्टर, स्थिरांक, क्षेत्र, विधियां, गुण, अनुक्रमणिका, ऑपरेटर, ईवेंट और नेस्टेड प्रकार भी हो सकते हैं, हालांकि यदि ऐसे कई सदस्यों की आवश्यकता है, तो आपको इसके बजाय अपने प्रकार को एक वर्ग बनाने पर विचार करना चाहिए।


एमएस से कुछ सुझाव कब संरचना का उपयोग करें और कब कक्षा का उपयोग करें:

विचार करें

एक वर्ग के बजाय एक संरचना को परिभाषित करना यदि प्रकार के उदाहरण छोटे और आमतौर पर अल्पकालिक होते हैं या आमतौर पर अन्य वस्तुओं में एम्बेडेड होते हैं।

बचें

किसी संरचना को तब तक परिभाषित करना जब तक कि सभी प्रकार की निम्न विशेषताएँ न हों:

  • यह तार्किक रूप से आदिम प्रकार (इंट, डबल, आदि) के समान एकल मूल्य का प्रतिनिधित्व करता है
  • यह 16 बाइट्स के तहत एक उदाहरण आकार है।
  • यह अपरिवर्तनीय है।
  • इसे बार-बार बॉक्सिंग नहीं करना पड़ेगा।

स्विच

switch स्टेटमेंट एक कंट्रोल स्टेटमेंट है जो उम्मीदवारों की सूची से निष्पादित करने के लिए एक स्विच सेक्शन का चयन करता है। एक स्विच स्टेटमेंट में एक या अधिक स्विच सेक्शन शामिल हैं। प्रत्येक स्विच सेक्शन में एक या एक से अधिक case लेबल होते हैं, उसके बाद एक या अधिक स्टेटमेंट होते हैं। यदि किसी मामले में लेबल का मिलान मूल्य नहीं है, तो नियंत्रण default अनुभाग में स्थानांतरित किया जाता है, यदि कोई है। केस फॉल-थ्रू सी # में समर्थित नहीं है, सख्ती से बोल रहा हूं। हालाँकि, यदि 1 या अधिक case लेबल खाली हैं, तो निष्पादन अगले case ब्लॉक के कोड का पालन करेगा जिसमें कोड है। यह एक ही कार्यान्वयन के साथ कई case लेबल के समूहन की अनुमति देता है। निम्नलिखित उदाहरण में, यदि month 12 के बराबर है, तो case 2 में कोड निष्पादित किया जाएगा क्योंकि case लेबल 12 1 और 2 को समूहबद्ध किया गया है। यदि कोई case ब्लॉक खाली नहीं है, तो अगले case लेबल से पहले एक break मौजूद होना चाहिए, अन्यथा कंपाइलर एक त्रुटि को चिह्नित करेगा।

int month = DateTime.Now.Month; // this is expected to be 1-12 for Jan-Dec

switch (month)
{
    case 12: 
    case 1: 
    case 2:
        Console.WriteLine("Winter");
        break;
    case 3: 
    case 4: 
    case 5:
        Console.WriteLine("Spring");
        break;
    case 6: 
    case 7: 
    case 8:
        Console.WriteLine("Summer");
        break;
    case 9:     
    case 10: 
    case 11:
        Console.WriteLine("Autumn");
        break;
    default:
        Console.WriteLine("Incorrect month index");
        break;
}

एक case को केवल संकलित समय पर ज्ञात मान द्वारा लेबल किया जा सकता है (उदाहरण 1 , "str" , Enum.A ), इसलिए एक variable एक वैध case लेबल नहीं है, लेकिन एक const या एक Enum मान है (साथ ही साथ कोई भी) शाब्दिक मूल्य)।

इंटरफेस

एक interface में विधियों, गुणों और घटनाओं के हस्ताक्षर होते हैं। व्युत्पन्न वर्ग सदस्यों को परिभाषित करता है क्योंकि इंटरफ़ेस में केवल सदस्यों की घोषणा शामिल है।

interface कीवर्ड का उपयोग करके एक इंटरफ़ेस घोषित किया जाता है।

interface IProduct
{
    decimal Price { get; }
}

class Product : IProduct
{
    const decimal vat = 0.2M;
    
    public Product(decimal price)
    {
        _price = price;
    }
    
    private decimal _price;
    public decimal Price { get { return _price * (1 + vat); } }
}

असुरक्षित

unsafe कीवर्ड का उपयोग प्रकार या विधि घोषणाओं में या इनलाइन ब्लॉक घोषित करने के लिए किया जा सकता है।

इस कीवर्ड का उद्देश्य प्रश्न में ब्लॉक के लिए C # के असुरक्षित सबसेट के उपयोग को सक्षम करना है। असुरक्षित सबसेट में पॉइंटर, स्टैक एलोकेशन, सी-लाइक एरे जैसे फीचर्स शामिल हैं।

असुरक्षित कोड सत्यापन योग्य नहीं है और इसीलिए इसका उपयोग हतोत्साहित किया जाता है। असुरक्षित कोड के संकलन के लिए C # कंपाइलर पर स्विच करने की आवश्यकता होती है। इसके अतिरिक्त, CLR के लिए आवश्यक है कि रनिंग असेंबली को पूरा भरोसा हो।

इन सीमाओं के बावजूद, असुरक्षित कोड के पास कुछ संचालन को अधिक प्रदर्शन करने वाले (जैसे सरणी अनुक्रमण) या आसान (जैसे कुछ अप्रबंधित पुस्तकालयों के साथ अंतर) बनाने में मान्य उपयोग हैं।

एक बहुत ही सरल उदाहरण के रूप में

// compile with /unsafe
class UnsafeTest
{
   unsafe static void SquarePtrParam(int* p)
   {
      *p *= *p; // the '*' dereferences the pointer.
      //Since we passed in "the address of i", this becomes "i *= i"
   }

   unsafe static void Main()
   {
      int i = 5;
      // Unsafe method: uses address-of operator (&):
      SquarePtrParam(&i); // "&i" means "the address of i". The behavior is similar to "ref i"
      Console.WriteLine(i); // Output: 25
   }
}

पॉइंटर्स के साथ काम करते हुए, हम उन्हें नाम से संबोधित करने के बजाय सीधे मेमोरी स्थानों के मूल्यों को बदल सकते हैं। ध्यान दें कि यह संभव मेमोरी भ्रष्टाचार को रोकने के लिए अक्सर निर्धारित कीवर्ड के उपयोग की आवश्यकता होती है क्योंकि कचरा कलेक्टर चीजों को इधर-उधर कर देता है (अन्यथा, आपको त्रुटि CS0212 मिल सकती है)। चूँकि एक चर जिसे "निश्चित" किया गया है, उसे नहीं लिखा जा सकता है, हमारे पास अक्सर एक दूसरा सूचक होना चाहिए जो पहले के समान स्थान की ओर इशारा करता है।

void Main()
{
    int[] intArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    UnsafeSquareArray(intArray);
    foreach(int i in intArray)
        Console.WriteLine(i);
}

unsafe static void UnsafeSquareArray(int[] pArr)
{
    int len = pArr.Length;

    //in C or C++, we could say
    // int* a = &(pArr[0])
    // however, C# requires you to "fix" the variable first 
    fixed(int* fixedPointer = &(pArr[0]))
    {
        //Declare a new int pointer because "fixedPointer" cannot be written to.
        // "p" points to the same address space, but we can modify it
        int* p = fixedPointer;

        for (int i = 0; i < len; i++)
        {
            *p *= *p; //square the value, just like we did in SquarePtrParam, above
            p++;      //move the pointer to the next memory space.
                      // NOTE that the pointer will move 4 bytes since "p" is an
                      // int pointer and an int takes 4 bytes

            //the above 2 lines could be written as one, like this:
            // "*p *= *p++;"
        }
    }
}

आउटपुट:

1
4
9
16
25
36
49
64
81
100

unsafe भी स्टैकलॉक के उपयोग की अनुमति देता है जो सी रन-टाइम लाइब्रेरी में _alloca की तरह स्टैक पर मेमोरी आवंटित करेगा। stackalloc का उपयोग करने के लिए हम उपरोक्त उदाहरण को संशोधित कर सकते हैं:

unsafe void Main()
{
    const int len=10;
    int* seedArray = stackalloc int[len];
    
    //We can no longer use the initializer "{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}" as before.
    // We have at least 2 options to populate the array. The end result of either
    // option will be the same (doing both will also be the same here).

    //FIRST OPTION:
    int* p = seedArray; // we don't want to lose where the array starts, so we
                        // create a shadow copy of the pointer
    for(int i=1; i<=len; i++)
        *p++ = i;
    //end of first option

    //SECOND OPTION:
    for(int i=0; i<len; i++)
        seedArray[i] = i+1;
    //end of second option

    UnsafeSquareArray(seedArray, len);
    for(int i=0; i< len; i++)
        Console.WriteLine(seedArray[i]);
}

//Now that we are dealing directly in pointers, we don't need to mess around with
// "fixed", which dramatically simplifies the code
unsafe static void UnsafeSquareArray(int* p, int len)
{
    for (int i = 0; i < len; i++)
        *p *= *p++;
}

(आउटपुट ऊपर जैसा है)

अंतर्निहित

implicit कीवर्ड एक रूपांतरण ऑपरेटर को ओवरलोड किया जाता है। उदाहरण के लिए, आप एक Fraction वर्ग की घोषणा कर सकते हैं जिसे जरूरत पड़ने पर स्वचालित रूप से एक double परिवर्तित किया जाना चाहिए, और इसे स्वचालित रूप से int से परिवर्तित किया जा सकता है:

class Fraction(int numerator, int denominator)
{
    public int Numerator { get; } = numerator;
    public int Denominator { get; } = denominator;
    // ...
    public static implicit operator double(Fraction f)
    {
        return f.Numerator / (double) f.Denominator;
    }
    public static implicit operator Fraction(int i)
    {
        return new Fraction(i, 1);
    }
}

सही गलत

true और false कीवर्ड के दो उपयोग हैं:

  1. शाब्दिक बूलियन मूल्यों के रूप में
var myTrueBool = true;
var myFalseBool = false;
  1. ऑपरेटर्स के रूप में जिन्हें ओवरलोड किया जा सकता है
public static bool operator true(MyClass x)
{
    return x.value >= 0;
}

public static bool operator false(MyClass x)
{
    return x.value < 0;
}

Nullable प्रकारों की शुरूआत से पहले, C # 2.0 से पहले गलत ऑपरेटर को ओवरलोड करना उपयोगी था।
एक प्रकार जो true ऑपरेटर को अधिभारित करता true , उसे false ऑपरेटर को भी अधिभारित करना चाहिए।

तार

string .NET डेटाटाइप System.String लिए एक अन्य नाम है। string , जो पाठ (वर्णों के अनुक्रम) संग्रहीत करने की अनुमति देता है।

संकेतन:

string a = "Hello";
var b = "world";
var f = new string(new []{ 'h', 'i', '!' }); // hi!

स्ट्रिंग में प्रत्येक वर्ण UTF-16 में एन्कोड किया गया है, जिसका अर्थ है कि प्रत्येक वर्ण को न्यूनतम 2 बाइट्स संग्रहण स्थान की आवश्यकता होगी।

ushort

एक संख्यात्मक प्रकार 16-बिट पॉजिटिव पूर्णांक को संग्रहीत करने के लिए उपयोग किया जाता है। ushort के लिए एक उपनाम है System.UInt16 , और स्मृति के 2 बाइट्स लेता है।

वैध सीमा 0 से 65535

ushort a = 50; // 50
ushort b = 65536; // Error, cannot be converted
ushort c = unchecked((ushort)65536); // Overflows (wraps around to 0)

sbyte

एक संख्यात्मक प्रकार जो 8-बिट हस्ताक्षरित पूर्णांक को संग्रहीत करने के लिए उपयोग किया जाता है। sbyte System.SByte लिए एक अन्य नाम है, और मेमोरी के 1 बाइट लेता है। अहस्ताक्षरित समकक्ष के लिए, byte उपयोग करें।

वैध सीमा -127 से 127 (चिह्न को संग्रहीत करने के लिए बचे हुए का उपयोग किया जाता है)।

sbyte a = 127; // 127
sbyte b = -127; // -127
sbyte c = 200; // Error, cannot be converted
sbyte d = unchecked((sbyte)129); // -127 (overflows)

वर

एक अनुमानित प्रकार का स्थानीय चर जो दृढ़ता से टाइप किया जाता है जैसे कि उपयोगकर्ता ने प्रकार घोषित किया था। अन्य चर घोषणाओं के विपरीत, संकलक उस चर के प्रकार को निर्धारित करता है जो यह उस मान के आधार पर प्रदर्शित होता है जो इसे सौंपा गया है।

var i = 10; // implicitly typed, the compiler must determine what type of variable this is
int i = 10; // explicitly typed, the type of variable is explicitly stated to the compiler

// Note that these both represent the same type of variable (int) with the same value (10).

अन्य प्रकार के चर के विपरीत, इस कीवर्ड के साथ परिवर्तनीय परिभाषाओं को घोषित किए जाने पर आरंभ करने की आवश्यकता होती है। यह वैर कीवर्ड के कारण होता है जो एक अनुमानित टाइप चर का प्रतिनिधित्व करता है।

var i;
i = 10;

// This code will not run as it is not initialized upon declaration.

Var कीवर्ड का उपयोग फ्लाई पर नए डेटाटाइप बनाने के लिए भी किया जा सकता है। इन नए डेटाटिप्स को गुमनाम प्रकार के रूप में जाना जाता है। वे काफी उपयोगी हैं, क्योंकि वे उपयोगकर्ता को किसी भी प्रकार के ऑब्जेक्ट प्रकार को स्पष्ट रूप से घोषित किए बिना गुणों के एक सेट को परिभाषित करने की अनुमति देते हैं।

सादा अनाम प्रकार

var a = new { number = 1, text = "hi" };

LINQ क्वेरी जो एक अनाम प्रकार लौटाती है

public class Dog
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class DogWithBreed
{
    public Dog Dog { get; set; }
    public string BreedName  { get; set; }
}

public void GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
             join b in db.Breeds on d.BreedId equals b.BreedId
             select new 
                    {
                        DogName = d.Name,
                        BreedName = b.BreedName
                    };

    DoStuff(result);
}

आप foreach स्टेटमेंट में var कीवर्ड का उपयोग कर सकते हैं

public bool hasItemInList(List<String> list, string stringToSearch)
{
    foreach(var item in list)
    {
        if( ( (string)item ).equals(stringToSearch) )
            return true;
    }

    return false;
}

प्रतिनिधि

प्रतिनिधि एक प्रकार है जो एक विधि के संदर्भ को दर्शाता है। उनका उपयोग अन्य तरीकों के तर्क के रूप में पारित करने के तरीकों के लिए किया जाता है।

प्रतिनिधि स्थिर विधियों, उदाहरण विधियों, अनाम विधियों, या लैम्ब्डा अभिव्यक्तियों को धारण कर सकते हैं।

class DelegateExample
{
    public void Run()
    {
        //using class method
        InvokeDelegate( WriteToConsole ); 
        
        //using anonymous method
        DelegateInvoker di = delegate ( string input ) 
        { 
            Console.WriteLine( string.Format( "di: {0} ", input ) );
            return true; 
        };
        InvokeDelegate( di ); 
        
        //using lambda expression
        InvokeDelegate( input => false ); 
    }

    public delegate bool DelegateInvoker( string input );

    public void InvokeDelegate(DelegateInvoker func)
    {
        var ret = func( "hello world" );
        Console.WriteLine( string.Format( " > delegate returned {0}", ret ) );
    }

    public bool WriteToConsole( string input )
    {
        Console.WriteLine( string.Format( "WriteToConsole: '{0}'", input ) );
        return true;
    }
}

एक प्रतिनिधि को एक विधि सौंपते समय यह ध्यान रखना महत्वपूर्ण है कि विधि में एक ही वापसी प्रकार और साथ ही पैरामीटर होना चाहिए। यह 'सामान्य' विधि अधिभार से भिन्न होता है, जहां केवल पैरामीटर विधि के हस्ताक्षर को परिभाषित करते हैं।

कार्यक्रम प्रतिनिधियों के शीर्ष पर बनाए गए हैं।

प्रतिस्पर्धा

एक event डेवलपर को अधिसूचना पैटर्न को लागू करने की अनुमति देती है।

सरल उदाहरण है

public class Server
{
    // defines the event
    public event EventHandler DataChangeEvent;

    void RaiseEvent()
    {
        var ev = DataChangeEvent;
        if(ev != null)
        {
            ev(this, EventArgs.Empty);
        }
    }
}

public class Client
{
    public void Client(Server server)
    {
        // client subscribes to the server's DataChangeEvent
        server.DataChangeEvent += server_DataChanged;
    }

    private void server_DataChanged(object sender, EventArgs args)
    {
        // notified when the server raises the DataChangeEvent
    }
}

MSDN संदर्भ

आंशिक

कीवर्ड partial का उपयोग प्रकार, वर्ग, संरचना या इंटरफ़ेस की परिभाषा के दौरान किया जा सकता है ताकि प्रकार की परिभाषा को कई फ़ाइलों में विभाजित किया जा सके। यह ऑटो जनरेटेड कोड में नई सुविधाओं को शामिल करने के लिए उपयोगी है।

File1.cs

namespace A
{
    public partial class Test
    {
        public string Var1 {get;set;}
    }
}

File2.cs

namespace A
{
    public partial class Test
    {
        public string Var2 {get;set;}
    }
}

नोट: एक वर्ग को किसी भी संख्या में फ़ाइलों में विभाजित किया जा सकता है। हालाँकि, सभी घोषणाएँ समान नामस्थान और समान विधानसभा के अंतर्गत होनी चाहिए।

partial कीवर्ड का उपयोग करके तरीकों को भी आंशिक घोषित किया जा सकता है। इस स्थिति में एक फ़ाइल में केवल विधि परिभाषा होगी और दूसरी फ़ाइल में कार्यान्वयन होगा।

एक आंशिक विधि में इसके हस्ताक्षर को आंशिक प्रकार के एक भाग में परिभाषित किया गया है, और इसके कार्यान्वयन को अन्य प्रकार के भाग में परिभाषित किया गया है। आंशिक तरीके क्लास डिजाइनरों को ईवेंट हैंडलर के समान विधि हुक प्रदान करने में सक्षम करते हैं, जो डेवलपर्स को लागू करने या न करने का निर्णय ले सकते हैं। यदि डेवलपर एक कार्यान्वयन की आपूर्ति नहीं करता है, तो संकलक संकलन समय पर हस्ताक्षर को हटा देता है। निम्नलिखित शर्तें आंशिक तरीकों पर लागू होती हैं:

  • आंशिक प्रकार के दोनों भागों में हस्ताक्षर मेल खाने चाहिए।
  • विधि शून्य लौटानी चाहिए।
  • किसी भी एक्सेस संशोधक की अनुमति नहीं है। आंशिक तरीके स्पष्ट रूप से निजी हैं।

- MSDN

File1.cs

namespace A
{
    public partial class Test
    {
        public string Var1 {get;set;}
        public partial Method1(string str);
    }
}

File2.cs

namespace A
{
    public partial class Test
    {
        public string Var2 {get;set;}
        public partial Method1(string str)
        {
            Console.WriteLine(str);
        }
    }
}

नोट: आंशिक विधि वाले प्रकार को भी आंशिक घोषित किया जाना चाहिए।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow