زنگ سی شارپ – قسمت بیست و یکم

آشنایی با constructor، کلمه کلیدی this و کلمه کلیدی static


مسعود درویشیان ۲۳ دیدگاه سی شارپ پنج شنبه, ۷ام دی , ۱۳۹۱ 20367 بازدید

در قسمت قبل به معرفی برنامه‌نویسی شی‌گرا، class ها، object ها و method ها پرداختیم. در این قسمت به ادامه‌ی مباحث قسمت قبل می‌پردازیم و همچنین با constructor و کلمات‌کلیدی this و static آشنا می‌شویم.

زنگ سی‌شارپ - قسمت بیستم و یکم

Constructor و چگونگی استفاده از آن

در قسمت قبل مشاهده کردید هنگامی‌که از یک کلاس، شیء می‌سازید به تک تک متغیرهای آن جداگانه مقدار می‌دهید:

BMW.Color = "Black";
BMW.Model = "M6";
BMW.MaxSpeed = 250;

اگر قصد دارید به‌صورت حرفه‌ای برنامه‌نویسی سی‌شارپ را دنبال کنید مسلماً این روش مقداردهی برای شما مناسب نیست. استفاده از این روش ممکن است باعث به‌وجود آمدن خطا در برنامه شود (شاید مقداردهی به یک فیلد فراموش شود). راه بهتر برای انجام این‌کار استفاده از constructor است. constructor یک شیء را هم‌زمان با ساخت آن، مقداردهی می‌کند. نام constructor باید برابر با نام همان کلاسی باشد که constructor در آن قرار دارد. constructor از لحاظ syntax مشابه به method است با این تفاوت که هیچ مقداری را برنمی‌گرداند و بدون ret-type نوشته می‌شود.

فرم کلی constructor به شکل زیر است:

access class-name(param-list) 
{
    // constructor code
}

اصولاً از constructor برای مقداردهی اولیه به متغیرهای کلاس یا اجرای یک‌سری عملیات، زمانی که شیء ساخته می‌شود، استفاده می‌کنید. نوع دسترسی (access modifier) به‌صورت public در نظر گرفته می‌شود زیرا constructor معمولاً خارج از کلاس‌ خودش فراخوانی می‌شود. Param-list می‌تواند خالی باشد یا این‌که یک یا چندین پارامتر داشته باشد.

چه شما constructor تعریف کرده باشید چه نکرده باشید، همه‌ی کلاس‌ها یک constructor دارند. زیرا سی‌شارپ به‌صورت اتوماتیک یک default constructor برای هر کلاس به‌وجود می‌آورد که به همه‌ی متغیرهای کلاس یک مقدار پیش‌فرض را اختصاص می‌دهد. برای بیشتر value type ها مقدار پیش‌فرض صفر، برای بولین مقدار پیش‌فرض false و برای reference type ها مقدار پیش‌فرض null در نظر گرفته می‌شود. زمانی که شما از constructor خودتان استفاده می‌کنید دیگر از default constructor استفاده نمی‌‌شود.

در این مثال ساده، استفاده از constructor را مشاهده می‌کنید:

using System;
class Car
{
    public string Color;

    public Car()
    {
        Color = "White";
    }
}

class Example
{
    static void Main()
    {
        Car BMW = new Car();
        Car mercedesBenz = new Car();

        Console.WriteLine(BMW.Color);
        Console.WriteLine(mercedesBenz.Color);
    }
}

در این مثال، constructor برابر است با:

public Car()
{
    Color = "White";
}

همان‌طور که می‌بینید دسترسی به‌صورت public تعریف شده است چراکه constructor خارج از کلاس خودش صدا زده می‌شود. این constructor توسط کلمه‌کلیدی new زمانی که شیء ساخته شد فراخوانی می‌شود و رشته‌ی “White” را به متغیر Color اختصاص می‌دهد.

برای مثال در این خط کد:

Car BMW = new Car();

Constructor این کلاس که ()Car نام دارد توسط شیء BMW صدا زده می‌شود و به BMW.Color مقدار “White” را اختصاص می‌دهد. همین داستان برای شیء mercedesBenz نیز صدق می‌کند.

در مثال قبل constructor ما هیچ پارامتری نداشت. در بیشتر مواقع شما نیاز دارید که یک یا چندین پارامتر برای constructor تان مشخص کنید. پارامترها از همان روشی که در قسمت قبل برای متدها بیان شد، در این‌جا نیز استفاده می‌شوند.

به مثال زیر توجه کنید:

using System;
class Car
{
    public string Color;

    public Car(string carColor)
    {
        Color = carColor;
    }
}

class Example
{
    static void Main()
    {
        Car BMW = new Car("Black");
        Car mercedesBenz = new Car("Yellow");

        Console.WriteLine(BMW.Color);
        Console.WriteLine(mercedesBenz.Color);
    }
}

در این مثال، کانستراکتور ()Car تنها یک پارامتر به نام carColor دارد که از آن برای مقدار دهی به متغیر Color استفاده می‌شود. بنابراین بعد از اجرای این خط کد:

Car BMW = new Car("Black");

رشته‌ی “Black” به متغیر carColor داده می‌شود و سپس به متغیر Color اختصاص می‌یابد.

به مثال زیر توجه کنید:

using System;
class Car
{
    public string Color;
    public string Model;
    public int MaxSpeed;

    public Car(string carColor, string carModel, int carMaxSpeed)
    {
        Color = carColor;
        Model = carModel;
        MaxSpeed = carMaxSpeed;
    }
}

class Example
{
    static void Main()
    {
        Car BMW = new Car("Black", "M6", 250);
        Car mercedesBenz = new Car("Yellow", "McLaren", 300);

        Console.WriteLine(BMW.Color + "\t" + BMW.Model + "\t" + BMW.MaxSpeed);
        Console.WriteLine(mercedesBenz.Color + "\t" + mercedesBenz.Model + "\t" 
            + mercedesBenz.MaxSpeed);
    }
}

در این برنامه، از چندین پارامتر برای constructor استفاده کرده‌ایم. در واقع توسط constructor شما برای ساخت اشیاء این اجبار را به‌وجود می‌آورید که همه‌ی field ها حتماً مقداردهی شوند.

کلمه‌کلیدی this

هنگامی‌که یک متد صدا زده می‌شود، متد به‌صورت اتوماتیک به شیء مربوط به خودش رجوع می‌کند. برای این‌که با کلمه‌کلیدی this آشنا شوید به مثال زیر توجه کنید:

using System;
class Rectangle
{
    public int Width;
    public int Height;
    public Rectangle(int w, int h)
    {
        Width = w;
        Height = h;
    }
    public int Area()
    {
        return Width * Height;
    }
}
class UseRect
{
    static void Main()
    {
        Rectangle r1 = new Rectangle(4, 5);
        Rectangle r2 = new Rectangle(7, 9);
        Console.WriteLine("Area of r1: " + r1.Area());
        Console.WriteLine("Area of r2: " + r2.Area());
    }
}

در این برنامه کلاسی به اسم Rectangle داریم که شامل دو متغیر، یک constructor و یک متد (که مساحت مستطیل را محاسبه می‌کند) است. درون متد، اعضای کلاس می‌توانند مستقیماً (بدون ساخت هیچ شیء‌ای از کلاس) قابل دسترسی باشند. بنابراین درون متد ()Area این خط کد:

return Width * Height;

به این معناست که Width و Height با توجه به شی‌ءای که از کلاس Rectangle ساخته می‌شود مقدار متفاوتی می‌توانند داشته باشند. این مقادیر که برای هر شیء متفاوت است، در هم ضرب می‌شوند و حاصل این ضرب return می‌شود. این خط کد را به روش زیر نیز می‌توانید بنویسید:

return this.Width * this.Height;

در این‌جا، کلمه‌کلیدی this به همان شیء‌ای رجوع می‌کند که در آن متد ()Area صدا زده شده است. بنابراین this.Width با مراجعه به شیء مربوطه، شامل مقداری است که آن شیء برای این متغیر دارد. this.Height نیز مشابه با همین قضیه است. برای مثال اگر ()Area از object ای به اسم x صدا زده شده باشد بنابراین (با توجه به خط کد قبلی) this به شیء x رجوع می‌کند.

همچنین می‌توانید از this در constructor استفاده کنید:

public Rectangle(int w, int h)
{
    this.Width = w;
    this.Height = h;
}

مثالی که پیش‌تر ذکر شد را با کلمه‌کلیدی this ببینید:

using System;
class Rectangle
{
    public int Width;
    public int Height;
    public Rectangle(int w, int h)
    {
        this.Width = w;
        this.Height = h;
    }
    public int Area()
    {
        return this.Width * this.Height;
    }
}
class UseRect
{
    static void Main()
    {
        Rectangle r1 = new Rectangle(4, 5);
        Rectangle r2 = new Rectangle(7, 9);
        Console.WriteLine("Area of r1: " + r1.Area());
        Console.WriteLine("Area of r2: " + r2.Area());
    }
}

در حقیقت، هیچ برنامه‌نویسی به این طریق که در برنامه بالا از this استفاده کردیم، استفاده نمی‌کند. زیرا در برنامه بالا استفاده از آن نه تنها سودی ندارد، بلکه فرم استاندارد آن بدون this راحت‌تر و ساده‌تر است. اما این‌طور نیست که this بی‌فایده باشد. برای مثال، سی‌شارپ اجازه می‌دهد نام local variables (متغیرهای محلی)، پارامترها وinstance variables  یکی باشند. وقتی چنین اتفاقی می‌افتد، پارامترها یا متغیرهای محلی، باعث می‌شوند نتوانید نام instance variables را ببینید. در این موارد شما برای دسترسی به instance variables باید از کلمه‌کلیدی this استفاده کنید. برای مثال، اگر پارامترهای constructor را به‌شکل زیر بنویسیم:

public Rectangle(int Width, int Height)
{
    this.Width = Width;
    this.Height = Height;
}

در این‌جا، نام پارامترها با نام instance variables یکی است و اجازه نمی‌دهد به instance variables دسترسی داشته باشید. بنابراین در این‌جا با استفاده از this می‌توانید به instance variables دسترسی یابید و مشخص کنید که منظورتان فیلدهای همان شیء‌ای است که با آن در ارتباط هستید.

String ها در سی‌شارپ

یکی از مهم‌ترین data type ها در سی‌شارپ، string است چراکه مشخص کننده‌ی رشته‌ای از کاراکترهاست. در بسیاری از زبان‌های برنامه‌نویسی، یک string آرایه‌ای از کاراکترهاست اما در سی‌شارپ چنین نیست. در سی‌شارپ، string ها object هستند. از این‌رو، string ها در دسته‌ی reference type قرار می‌گیرند. شما از ابتدای مقالات زنگ سی‌شارپ از string استفاده می‌کردید اما از ماهیت آن خبر نداشتید. هنگامی‌که بین دابل کوتیشن، رشته‌ای از کاراکترها را قرار می‌دادید در واقع یک شیء می‌ساختید که از جنس string بود.

ساده‌ترین روش تعریف string به این صورت است:

string str = "C# Strings are powerful.";

در این‌جا متغیر str یک reference variable است و در واقع آدرس مکانی که شیء ساخته شده از جنس string در آن قرار دارد را، در خود ذخیره می‌کند.

شما همچنین می‌توانید با آرایه‌ای از جنس char یک string بسازید:

using System;
class Example
{
    static void Main()
    {
        char[] charArray = {'C','#',' ', 'T', 'i', 'm', 'e'};
        string str = new string(charArray);
        Console.WriteLine(str);
    }
}

زمانی‌که شما یک شیء string می‌سازید تقریباً می‌توانید هرجایی‌که وارد کردن دابل کوتیشن مجاز است، از آن استفاده کنید. برای مثال می‌توانید از شیء string به‌عنوان argument در متد ()WriteLine استفاده کنید:

using System;
class Example
{
    static void Main()
    {
        char[] charArray = {'C','#',' ', 'T', 'i', 'm', 'e'};
        string str1 = new string(charArray);
        string str2 = "webtarget.ir";

        Console.WriteLine(str1);
        Console.WriteLine(str2);
    }
}

آرایه‌ی string ها

مانند دیگر دیتا تایپ‌ها، string نیز می‌تواند در یک آرایه ذخیره شود:

using System;
class Example
{
    static void Main()
    {
        string[] strArray = {"This", "is", "a", "string", "array." };

        Console.WriteLine("Orginal Array: ");
        for (int i = 0; i < strArray.Length; i++)
        {
            Console.Write(strArray[i] + " ");
        }
        Console.WriteLine("\n");

        // change a string.
        strArray[1] = "was";
        strArray[4] = "array, too.";

        Console.WriteLine("Modified Array: ");
        for (int i = 0; i < strArray.Length; i++)
        {
            Console.Write(strArray[i] + " ");
        }
        Console.WriteLine("\n");
    }
}

خروجی:

به مثال بعدی توجه کنید:

using System;
class Example
{
    static void Main()
    {
        string str = "This is a string";

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

string ها read only هستند. به این معنا که، تنها می‌توانید مقدار آن‌را بخوانید و نمی‌توانید مقدار یک string را تغییر دهید. برای مثال، اگر بنویسید “string name = “Amin و در خط بعد بنویسید “string name = “Hamed  رشته‌ی “Amin” هنوز در حافظه‌ی کامپیوتر شما موجود است اما متغیر name دیگر به این شیء رجوع نمی‌کند و در واقع آدرس شیء جدیدی را که تعریف کردیم در خود نگه می‌دارد. بنابراین نمی‌توانید محتوای یک string را تغییر دهید و در واقع یک شیء جدید به‌وجود می‌آورید.

کلمه‌ی کلیدی static

گاهی نیاز دارید که اعضای یک کلاس به هیچ شیء‌ای وابسته نباشند. به‌طور معمول، اعضای کلاس، از طریق شیء‌ای که از آن کلاس ساخته می‌شود قابل دسترسی هستند اما شما می‌توانید عضوی از کلاس را طوری تعریف کنید که بدون ساخت هیچ شیء‌ای، مستقیماً  (از طریق نام کلاس و عملگر نقطه) به آن دسترسی داشته باشید. برای ساخت چنین عضوی، قبل از تعریف آن عضو از کلمه‌ی‌کلیدی static استفاده می‌کنید. هنگامی که عضوی از یک کلاس به‌صورت static تعریف می‌شود آن عضو بدون ساخت هیچ object ای از کلاس قابل دسترسی و در واقع مستقل از اشیاء است و به هیچ شیء‌ای از آن کلاس وصل نمی‌شود. شما می‌توانید هم متدها و هم متغیرها را به‌صورت static تعریف کنید و حتماً تا این لحظه‌ی متوجه‌ی این کلمه‌ی‌کلیدی در متد ()Main شده‌اید. از آن‌جا که متد ()Main نقطه‌ی شروع برنامه‌تان و یکی از اعضای کلاس است، باید قبل از هرچیز و پیش از ساخت هرگونه شیء‌ای، صدا زده شود. به این دلیل است که متد ()Main را به‌صورت static تعریف می‌کنیم تا قبل از اینکه شیء‌ای از کلاس ساخته شود، متد ()Main فراخوانی شده تا درون این متد بتوانیم کنترل برنامه را به‌دست بگیریم.

به مثال زیر توجه کنید:

// Use static.
using System;
class MyClass
{
    // A static variable.
    public static int Variable = 100;

    // A static method.
    public static int MyMethod()
    {
        return Variable + 20;
    }
}
class StaticDemo
{
    static void Main()
    {
        Console.WriteLine("Initial value of MyClass.Variable is " + MyClass.Variable);

        MyClass.Variable = 8;
        Console.WriteLine("MyClass.Variable is " + MyClass.Variable);

        Console.WriteLine("MyClass.MyMethod(): " + MyClass.MyMethod());
    }
}

در این برنامه کلاس MyClass شامل یک متغیر static و یک متد static است بنابراین برای استفاده از این دو، نیازی نیست که از کلاس آن‌ها یک شیء بسازیم. همان‌طور که می‌بینید در متد ()Main بدون ساخت هیچ شیء‌ای از کلاس MyClass به‌راحتی توانسته‌ایم به دو عضو static کلاس MyClass دسترسی داشته باشیم. هنگامی‌که در یک کلاس هم عضو عادی وجود داشته باشد و هم عضو static، شما تنها می‌توانید به اعضای static دسترسی داشته باشید.

برای مثال، این‌جور نحوه‌ی استفاده نادرست است:

class MyClass
{
    public int Val1 = 10; // instance variable
    public static int Val2 = 20; // static variable

    public static int MyMethod()
    {
        // This is illegal!
        return Val2 / Val1; // won't complie
    }
}

متد static تنها می‌تواند به اعضای static دسترسی داشته باشد و نمی‌تواند مستقیماً به اعضای عادی کلاس دسترسی پیدا کند زیرا اعضای عادی یک کلاس حتماً باید به یک شیء وصل شوند تا مقدارشان در آن شیء ذخیره شود اما اعضای static مستقل از اشیاء هستند و می‌توان مستقیماً به آن‌ها دسترسی پیدا کرد. اگر قصد دارید درون یک متد static به اعضای عادی نیز دسترسی داشته باشید باید از طریق یک شیء این‌کار را انجام دهید:

class MyClass
{
    public void NonStaticMethod()
    {
        Console.WriteLine("This is a non static method");
    }

    public static void StaticMethod(MyClass ob)
    {
        ob.NonStaticMethod(); // this is ok
    }
}

کلاس بالا کاملاً صحیح است. ما از طریق یک متد static به یک عضو غیر static دسترسی پیدا کردیم اما این کار را از طریق یک شیء پاس داده شده به متد انجام دادیم. هنگامی‌که در متد ()Main، متد ()StaticMethod را صدا بزنیم باید یک شیء را به آن به عنوان argument به آن بدهیم. درون متد ()StaticMethod پارامتر ob این argument را (که یک شیء است) دریافت می‌کند و می‌تواند از طریق این شیء به اعضای غیر static کلاس آن دسترسی داشته باشد.

به مثال زیر توجه کنید:

using System;
class Example
{
    static void Main()
    {
        PrintHello();
        SayHello("World!");
        string str = MakeHello("Here i am...");
        Console.WriteLine(str);
        
        // Console.WriteLine(MakeHello("Here i am..."));
    }

    static void PrintHello()
    {
        Console.WriteLine("Hello!");
    }

    static void SayHello(string name)
    {
        Console.WriteLine("Hello " + name);
    }

    static string MakeHello(string name)
    {
        return "Hello " + name;
    }
}

در این برنامه، در کلاس Example، علاوه بر متد ()Main، سه متد static دیگر وجود دارد که هرکدام کار ساده‌ای را انجام می‌دهند. برای این‌که بتوانیم در متد ()Main مستقیماً از این متدها (بدون ساخت شیء) استفاده کنیم باید آن‌ها را به‌صورت static تعریف کنیم.

به مثال زیر توجه کنید:

using System;
class Example
{
    static void Main()
    {
        double i, j;
        i = 10;
        j = 20;

        Console.WriteLine(Average(i, j));

        Console.WriteLine(Average(2, 6));

        Console.WriteLine(Average(5.3, 6.2));

    }


    static double Average(double a, double b)
    {
        return (a + b) / 2;
    }
}

در این برنامه از متدی استفاده کرده‌ایم که دو عدد را می‌گیرد و میانگین آن‌ها را محاسبه می‌کند. این متد را به‌صورت static تعریف کرده‌ایم، بنابراین می‌توانیم مستقیماً در متد ()Main از آن استفاده کنیم. توجه کنید که اگر این متد را به‌صورت static تعریف نکنید نمی‌توانید مستقیماً در متد ()Main به آن دسترسی داشته باشید. زیرا متد ()Main به‌صورت static تعریف می‌شود و درصورتی می‌تواند مستقیماً به متد ()Average دسترسی داشته باشد که آن هم static باشد.

در صورتی‌که متد ()Average به‌صورت static نباشد باید این‌گونه عمل کنیم:

using System;
class Example
{
    static void Main()
    {
        double i, j;
        i = 10;
        j = 20;

        Example ob = new Example();
        Console.WriteLine(ob.Average(i, j));
        Console.WriteLine(ob.Average(2.3, 5.4));
    }
    private double Average(double a, double b)
    {
        return (a + b) / 2;
    }
}

همان‌طور که می‌‌بینید، برای استفاده از متد ()Average که دیگر static نیست، مجبوریم در ابتدا یک شیء از کلاس آن بسازیم تا بتوانیم به آن دسترسی داشته باشیم.

کلاس static

شما همچنین می‌توانید یک کلاس را به‌صورت static تعریف کنید. هنگامی‌که یک کلاس را به‌صورت static تعریف می‌کنید (۱) دیگر نمی‌توانید از روی این کلاس شیء بسازید (۲) همه‌ی اعضای کلاس باید static باشند.

در مثال زیر یک ماشین حساب ساده را، از طریق کلاس static می‌سازیم:

using System;
static class Calculator
{
    public static double Add(double a, double b)
    {
        return a + b;
    }
    public static double Subtract(double a, double b)
    {
        return a - b;
    }
    public static double Multipliction(double a, double b)
    {
        return a * b;
    }
    public static double Division(double a, double b)
    {
        if (b == 0)
        {
            Console.WriteLine("Connat divide by zero");
            return -1;
        }
        return a / b;
    }
}
class MainClass
{
    static void Main()
    {
        int i, j;
        i = 4;
        j = 2;

        Console.WriteLine("i: {0}, j: {1}", i, j);
        Console.WriteLine("Add: {0}", Calculator.Add(i, j));
        Console.WriteLine("Subtract: {0}", Calculator.Subtract(i, j));
        Console.WriteLine("Multipliction: {0}", Calculator.Multipliction(i, j));
        Console.WriteLine("Division: {0}", Calculator.Division(i, j));

        j = 0;
        Calculator.Division(i, j);

        // Calculator ob = new Calculator(); // Wrong!
    }
}

همان‌طور که می‌بینید، تمام اعضای کلاس static باید static باشند و همچنین دیگر برای استفاده از این کلاس نیازی نیست که از آن شیء بسازید (اگر بخواهید هم نمی‌توانید). درکل، زمانی یک کلاس را به‌صورت static تعریف می‌کنید که همه‌ی اعضای آن static باشند و نیازی به ساختن شیء از آن کلاس نداشته باشید. همچنین زمانی‌که ازextension method استفاده می‌کنید، باید کلاس مربوطه static باشد. در مقالات آینده با extension method آشنا می‌شوید.



نویسنده / مترجم : مسعود درویشیان

علاقه مند به موسیقی و برنامه نویسی بازی


۲۳ دیدگاه برای این نوشته ثبت شده است


  1. فرشید
    ۸ دی ۱۳۹۱

    ممنون از زحمات شما و خسته نباشید.



  2. مفید بود..موفق باشید




  3. داوود
    ۹ دی ۱۳۹۱

    سلام آقا مسعود؛ دستتون درد نکنه؛ دیگه یواش یواش داریم به قسمتهای پیشرفته و خوبش می رسیم.
    فقط اینکه تمرین بعدا می دید؟
    میخواین به یک سطح مشخصی برسیم؟
    بازهم ممنون از زحمات شما و خسته نباشید.




    • مسعود درویشیان
      ۹ دی ۱۳۹۱

      سلام. بله توی قسمت بعدی، بیشتر تمرین و کار کردن روی چیزایی هست که تا الان گفتیم. تمرین هم می‌دیم…




  4. داوود
    ۱۵ دی ۱۳۹۱

    سلام مسعودجان؛
    امیدوارم حالت خوب باشه؛
    یه سوال داشتم ازتون؛ در این قسمت که نوشتید: “وقتی چنین اتفاقی می‌افتد، پارامترها یا متغیرهای محلی، باعث می‌شوند نتوانید نام instance variables را ببینید. در این موارد شما برای دسترسی به instance variables باید از کلمه‌کلیدی this استفاده کنید.”
    میشه یه مقدار بیشتر توضیح بدید؟؟
    به این شکل دقت کنید؛
    http://upload.tehran98.com/img1/g4ejk7x4qhf5orb540.jpg

    چرا علیرغم اینکه در خطوط ۴ و ۵ به ترتیب width و height رو تعریف کردیم؛بازم در سازنده داریم اونها رو تعریف می کنیم؟ نمیشد این دو خط رو حذف کرد؟ در واقع در اینجا اینها متغیرهای محلی ما هستند؟
    در جایی که گفته اید نمیتوانیم نام instance variable ها را ببینیم، پس چرا الان و در انتهای تصویر داریم اونها رو می بینیم و قابل دسترسی هستند؟(بدون اینکه از this استفاده کنیم؟؟)
    ببخشید که با سؤالاتم وقت شما رو گرفتم.




    • مسعود درویشیان
      ۱۵ دی ۱۳۹۱

      سلام
      وقت به‌خیر

      ببین داوود جان، هدف ما از اضافه کردن constructor به کلاس چی بود؟ این‌کارو انجام می‌دادیم تا وقتی از روی این کلاس داره شیء ساخته می‌شه یه سری عملیات انجام بشه یا مثلاً این اجبار رو به‌وجود بیاریم که فیلدهای کلاس رو در حین ساخت شیء مقدار دهی کنیم. خوب این constructor یه‌جورایی مثل متد هست، پارامتر داره اما چیزی برنمی‌گردونه. حالا این پارامترهایی که داره باعث می‌شه از اونور که داریم از کلاسش شیء می‌سازیم حتماً این مقادیری رو که می‌خواد بهش پاس بدیم. خوب ما این پارامترهارو به هر اسمی که دوست داشته باشیم نام‌گذاری می‌کنیم. دقت کن این فیلدهایی که تعریف کردیم اسم‌شون هم گذاشتیم Width و Height ربطی به پارامترهای constructor ندارن! constructor ما دوتا پارامتر برای خودش داره که دوست داشه اسمشون Width و Height باشه. خوب حالا داخل بلاک constructor، وقتی شما می‌خوای از Width یا Height استفاده کنی کامپایلر از کجا باید بفهمه که منظورت کدوم Width یا Height هست؟ از کجا بدونه منظورت فیلدها هستن یا پارامترها؟ خوب یه تداخل به‌وجود میاد دیگه نه؟ الان داخل constructor اسم پارامترها اجازه نمی‌دن تو بتونی اسم فیدهای Width و Height رو ببینی (چون هم‌اسم هستن) و اینی که الان داری میبینی اسم پارامتراست! برای این‌که بتونی به اسم فیلدها هم دسترسی داشته باشی از کلمه‌کلیدی this استفاده می‌کنی. این‌جا با کلمه‌کلیدی this مشخص می‌کنی که منظورت فیلدها هستن.
      اونجایی هم که تو تصویر داری توی متد ()Main به Width و Height از طریق شیء‌ای که ساختی دسترسی پیدا می‌کنی یه چیز طبیعیه! فیلدهاتو public تعریف کردی، بایدم بتونی دسترسی داشته باشی. اما توی constructoret، تو فیدهارو مقداردهی نکردی فقط داری با پارامترهات کار می‌کنی. میبینی؟ خط سبز هم زیرشون کشیده و بهت warning می‌ده که: داری یه متغیر رو مساویه خودش قرار می‌دی، آیا منظورت یه چیزه دیگه نبوده؟!




      • داوود
        ۱۵ دی ۱۳۹۱

        سلام مجدد مسعود جان؛
        واقعا دستت درد نکنه از پاسخ خوب و مبسوطی که نوشتی؛ یک دنیا ممنون و تشکر از لطف حضرتعالی.
        همچنین از شما بخاطر ارسال پاسخ در کمترین زمان ممکن و اینکه وقتتون رو در اختیار من قراردادی کمال قدردانی و امتنان رو دارم.
        موفق باشی




  5. داوود
    ۱۷ دی ۱۳۹۱

    دوباره سلام؛ ببخشید از اینکه زیاد سوال می پرسم؛
    در این تکه برنامه:

    class MyClass
    {
        public void NonStaticMethod()
        {
            Console.WriteLine("This is a non static method");
        }
    
        public static void StaticMethod(MyClass ob)
        {
            ob.NonStaticMethod(); // this is ok
        }
    }
    

    شما نوشته اید “این کار را از طریق یک شیء پاس داده شده به متد انجام دادیم. هنگامی‌که در متد ()Main، متد ()StaticMethod را صدا بزنیم باید یک شیء را به آن به عنوان argument به آن بدهیم.”
    چطوری یک شی ء رو میتونیم پاس بدیم؟ متغیر و یا پارامتر راحته ولی شی رو چجوری میشه؟ من اینجوری نوشتم که بتونیم بدون دادن پارامتری به خواسته مون برسیم ولی میخوام بدونم چچوری یک شی ء رو به متدمون پاس بدیم؟ به نظرتون من درست نوشتم؟(البته بدون شی)

    class MyClass
    {
        static void Main()
        {
            staticmethod();
        }
        public void nonstaticmethod()
        {
            Console.WriteLine("non static method");
        }
    
        public static void staticmethod()
        {
            MyClass ob = new MyClass();
            ob.nonstaticmethod();
        }
    }
    

    و اینکه در این تکه کد من با استفاده از متد استاتیک یک متد غیراستاتیک را فراخوانی کرده ام. آیا این کار درست صورت گرفته و همینجوری هستش؟

    class MyClass
    {
        public void NonStaticMethod()
        {
            Console.WriteLine("This is a non static method but access by static method");
        }
    
        public static void StaticMethod()
        {
            MyClass dd = new MyClass();
            dd.NonStaticMethod();
        }
    
        static void Main()
        {
            StaticMethod();
        }
    }
    

    بازم ازتون پوزش می خوام. ببخشید.




    • مسعود درویشیان
      ۱۷ دی ۱۳۹۱

      بله همه‌اش درسته، اما فکر کنم پارامتر بدید بهتره، این‌جوری‌که نوشتید بعد از هربار فراخوانی متد، یه شیء هم ساخته می‌شه که خیلی جالب نیست. به‌صورت پارامتر باشه بهتره مثال زیر هم شاید بتونه کمکتون کنه:

      using System;
      class StaticMethodDemo
      {
          public void NonStaticMethod()
          {
              Console.WriteLine("This is a non static method");
          }
      
          public static void StaticMethod(StaticMethodDemo ob)
          {
              ob.NonStaticMethod(); // this is ok
          }
      }
      class MyClass
      {
          static void Main()
          {
              StaticMethodDemo sm = new StaticMethodDemo();
              sm.NonStaticMethod();
      
              StaticMethodDemo.StaticMethod(sm);
          }
      }
      



      • داوود
        ۱۸ دی ۱۳۹۱

        ممنونم ازتون؛ آره مثالتون خیلی خوب بود و قابل فهم.
        بازم متشکرم از لطفتون.




      • محمد
        ۵ شهریور ۱۳۹۳

        اون SM ای که تو خط ۲۱ مثالتون هست برای چیه؟؟؟؟




        • محمد
          ۵ شهریور ۱۳۹۳

          اَاَاَاَ ممنون فهمیدم خدا خیرتون بده




  6. نوید
    ۲۱ دی ۱۳۹۱

    آقای درویشیان؛
    سلام
    مقدور هست برای شما که مثال آخری رو که در پاسخ آقای داوود فرستادید توضیح کوچکی بدهید؟




    • مسعود درویشیان
      ۲۲ دی ۱۳۹۱

      بحث اینه که ما توی یه متد static نمی‌تونیم به اعضای غیر static دسترسی داشته باشیم اما اگر قصد داریم این‌کار رو انجام بدیم باید از طریق یه شیء این کار رو انجام بدیم چون اعضای عادی یه کلاس حتماً باید به یک شیء وصل بشن تا مقدارشون توی اون شیء ذخیره بشه اما اعضای static مستقل از اشیاء هستند. ما هم توی این مثال از طریق یک متد static به یک عضو غیر static دسترسی پیدا کردیم اما این کار را از طریق یک شیء پاس داده شده به متد انجام دادیم.




  7. Mersad
    ۱۷ مرداد ۱۳۹۲

    سلام
    واقعا از خوندن جلسات آموزش سی شارپ شما، لذت می برم.
    گام به گام دارم با جلساتتون پیش میرم.
    متشکر از زحماتتون

    چندتا ابهام در قسمت String در سی شارپ برام بوجود اومده.
    اول اینکه شما فرمودید “در سی‌شارپ، string ها object هستند. از این‌رو، string ها در دسته‌ی reference type قرار می‌گیرند.”

    الان دستور زیر reference type هست یا value type ؟

     string str = "Simple String"; 

    و دستور زیر از چه نوعیه و تفاوتش با دستور بالایی در چیه؟

    char[] charArray = { 'S', 'i', 'm', 'p', 'l', 'e', ' ', 'S', 't', 'r', 'i', 'n', 'g' };
                string str = new string(charArray);

    سوال بعدیم هم اینه که شما در همین مقاله فرمودین “برای مثال، اگر بنویسید “string name = “Amin و در خط بعد بنویسید “string name = “Hamed رشته‌ی “Amin” هنوز در حافظه‌ی کامپیوتر شما موجود است اما متغیر name دیگر به این شیء رجوع نمی‌کند و در واقع آدرس شیء جدیدی را که تعریف کردیم در خود نگه می‌دارد.”

    منظرتون اینه :
    php]string name = “Amin”;
    string name = “Hamed”;[/php]

    خب این کد به خودیه خود خطا میده که!!! و name نمیتونه از Amin به Hamed تغییر کنه.
    لطفا راهنماییم کنید.




    • مسعود درویشیان
      ۲۰ مرداد ۱۳۹۲

      رشته‌ها reference type هستن، “Simple String” که نوشتید هم reference type هست فرقی نمی‌کنه. اون قسمتی که یه آرایه از char دارین به این صورت هست که یکی از constructor های string می‌تونه یه آرایه از جنس char دریافت کنه و اون رو به یه رشته تبدیل کنه، همین. ممکنه توی یه موقعیتی به این قابلیت نیاز داشته باشید که ازش استفاده کنید اما در حالت عادی، مستقیماً رشته رو می‌نویسید. در مورد سوال آخر هم این‌که، بله درست می‌گید، باید کلمه string رو دیگه ننویسید تا دوباره نخواهد مجددا متغیر name رو (که قبلاً تعریف شده) دوباره تعریف کنه و خطا بگیره. فقط از اسم متغیر (name) استفاده کنید




  8. Mersad
    ۱۷ مرداد ۱۳۹۲

    سلام
    یه سوال دیگه هم داشتم از خدمتتون

    اگه ما در یک کلاس، کلا اعضاش رو ( یا اون اعضاییش که بهشون احتیاج داریم رو) static تعریف کنیم، میتونیم ازش بدون ایجاد شی استفاده کنیم و مشکلی پیش نمیاد، پی چه احتیاجی هست که خود اون کلاس رو هم static تعریف کنیم؟
    مثلا تو همین مثلا آخر (مثال ماشین حساب ساده) اگه کلمه static رو از قبل کلمه ی class پاک کنیم، هیچ مشکلی برای برنامه پیش نمیاد و درست جواب میده.




    • مسعود درویشیان
      ۲۰ مرداد ۱۳۹۲

      وقتی یه کلاس به‌صورت static تعریف می‌شه، همه‌ی اعضای آن باید به اجبار static باشند و از روی اون کلاس هم نمی‌شه شیء ساخت. اگر static تعریف نکنید هم مشکلی براتون پیش نمیاد، این محدودیتی هست که برنامه‌نویس (با توجه به شرایط مد نظر خودش) واسه کلاس‌ای که تعریف می‌کنه می‌تونه اعمال کنه




  9. a-p
    ۱۵ مرداد ۱۳۹۳

    بسم الله الرحمن الرحیم
    سلام
    واقعیتش برای فهم جامع تر thisنیاز به توضیخات بیشتری دارم چون در آموزشهای تصویری کاربردهای متنوعی ازش دیدم




  10. G.Roshan
    ۲۴ دی ۱۳۹۵

    سلام دوستان گرامی
    یک سوال داشتم ، اگر راهنمایی بفرمایید ممنون میشم.

    اینکه فرق متد و تابع در سی شارپ چی هست ؟




  11. omid
    ۷ اردیبهشت ۱۳۹۶

    سلام جناب ممنون از اموزش خوبتون …استاد ما یه سوال داده برای من نامفهومه
    گفته کلاس set را بگونه ای بنویسید که دستورات زیر قابل اجرا باشد
    (set s1,s2(25),s3(5,6,7,8
    (s3.add(9
    (s2.add(1,10
    ممنون میشم راهنمایی کنید




  12. امیر
    ۱۸ مرداد ۱۳۹۶

    عالی بود



دیدگاه خود را بنویسید





نشانی ایمیل شما منتشر نخواهد شد.

کامنت های شما بعد از تأیید توسط نویسنده وبلاگ، منتشر خواهند شد.

لطفا دیدگاهتان تا حد امکان مربوط به پست بالا باشد. اگر حرف دیگری دارید و یا قصد تماس با من را دارید، از فرم تماس استفاده کنید.

شما میتوانید با مراجعه به سایت گراواتار یک آواتار اختصاصی برای خود تعریف کنید، تا در کنار نام شما نمایش داده شود

برای قرار دادن کدهای نمونه می توانید از تگ های [php] ، [html] ، [css] و [js] استفاده کنید.
به عنوان مثال کدهای php را می توان به صورت زیر قرار داد:
[php] var $whoLoveIranians = "WebTarget!"; [/php]



کلیه حقوق مادی و معنوی برای وب سایت وب تارگت محفوظ است ©2017 وب‌تارگت

استفاده از مطالب وب سایت در سایر وب سایت‌ها و نشریات چاپی با ذکر منبع آزاد است.