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

توضیحاتی در مورد operator overloading و ادامه حل تمرین شماره 14


مسعود درویشیان ۶۱ دیدگاه سی شارپ دوشنبه, ۳۰ام اردیبهشت , ۱۳۹۲ 37991 بازدید

در قسمت قبلی زنگ سی‌شارپ، در حل تمرین شماره‌ی ۱۴، توانستید برای هر هنرمند آلبوم ذخیره کنید، هنرمند را حذف کنید و آلبوم‌های ذخیره شده را مشاهده کنید. همچنین به تفاوت == و متد ()Equals پی بردید و اندکی با namespace آشنا شدید. در این قسمت در مورد Operator Overloading صحبت خواهیم کرد و سپس به ادامه‌ی حل تمرین شماره ۱۴ می‌پردازیم.

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

Operator Overloading

سی‌شارپ به شما اجازه می‌دهد operator (عملگر) هایی تعریف کنید که مرتبط به کلاس‌هایی است که خودتان می‌سازید. به این پروسه، operator overloading گفته می‌شود. با overload کردن یک operator، شما کاربرد آن operator را به کلاس خودتان اضافه می‌کنید. تاثیری که این operator روی کلاس شما می‌گذارد کاملاً تحت کنترل خودتان است و ممکن است برای هر کلاس متفاوت باشد. به‌عنوان مثال، کلاسی که یک لیست پیوندی تعریف می‌کند، ممکن است از عملگر + برای افزودن یک شیء به انتهای لیست، استفاده کند. کلاسی که stack را اجرا می‌کند، ممکن است از عملگر + برای افزودن یک شیء به بالای پشته، استفاده کند. کلاسی دیگر ممکن است از عملگر + به‌طور کاملاً متفاوت استفاده کند.

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

مزیت اصلی operator overloading این است که به شما اجازه می‌دهد به‌طور یکپارچه، یک کلاس جدید را در محیط برنامه‌نویسی خود، ادغام کنید. این ویژگی که به آن type extensibility می‌گویند، یکی از بخش‌های مهم یک زبان برنامه‌نویسی شی‌گرا مثل سی‌شارپ است. هنگامی‌که operator ها برای یک کلاس تعریف می‌شوند، می‌توانید آن operator را روی اشیای کلاس مربوطه، اعمال کنید. این نکته قابل ذکر است که operator overloading یکی از قدرمندترین ویژگی‌های سی‌شارپ است.

اصول Operator Overloading

Operator overloading شباهت زیادی با Method overloading دارد. برای overload کردن یک عملگر، از کلمه‌ی کلیدی operator برای تعریف یک operator method استفاده می‌کنیم که برای یک عمل خاص، مربوط به کلاس خودش، تعریف می‌شود.

دو حالت از operator method وجود دارد: unary operators (عملگرهای تکی) و binary operators (عملگرهای دوتایی). فرم کلی هرکدام را در زیر می‌بینید:

// General form for overloading a unary operator
public static ret-type operator op(param-type operand)
{
    // operations
}

// General form for overloading a binary operator
public static ret-type operator op(param-type1 operand1, param-type1 operand2)
{
    // operations
}

در این‌جا، عملگری که آن را overload می‌کنید، مثل + یا / ، جایگزین op می‌شود. ret-type مشخص کننده‌ی نوع مقداری است که return خواهد شد. اگرچه return type می‌تواند از هر نوعی باشد اما اغلب از نوع همان کلاسی است که operator در آن overload می‌شود. این ارتباط (یکسان بودن return type با جنس کلاس) باعث راحتی استفاده از عمگرهای overload شده می‌شود. برای unary operator ها، عملوند در قسمت operand قرار می‌گیرد. برای binary operator ها، عملوندها در قسمت operand1 و operand2 قرار خواهد گرفت. توجه داشته باشید که operator method ها باید هم public و هم static باشند.

در unary operator ها، نوع عملوند (operand) باید با نوع کلاسی که operator در آن تعریف می‌شود، یکسان باشد. بنابراین نمی‌توانید operator های سی‌شارپ را برای اشیایی که خودتان نساخته‌اید، تعریف کنید. برای مثال، نمی‌توانید مجدداً عملگر + را برای int و string تعریف کنید.  نکته‌ی دیگر اینکه، operator parameters نباید از ref وout  استفاده کنند.

برای این‌که بیشتر با operator overloading آشنا شوید، مثالی خواهیم زد که در آن binary operator های + و – را overload می‌کنیم. برنامه زیر کلاسی به اسم TwoD دارد که مختصات دوبعدی یک شیء را نگه‌داری می‌کند. عمگر + که آن را overload کرده‌ایم، مختصات یک شیء TwoD را با یک شیء دیگر TwoD جمع می‌کند. عملگر – نیز مختصات یک شیء را از دیگری کم می‌کند.

using System;
// A two-dimensional coordinate class.
class TwoD
{
    private int X, Y; // 2-D coordinates

    // Constructors
    public TwoD() { X = 0; Y = 0; }
    public TwoD(int x, int y)
    {
        this.X = x;
        this.Y = y;
    }

    // Overload binary +
    public static TwoD operator +(TwoD ob1, TwoD ob2)
    {
        TwoD result = new TwoD();

        result.Y = ob1.Y + ob2.Y;
        result.X = ob1.X + ob2.X;

        return result;
    }

    // Overload binary -
    public static TwoD operator -(TwoD ob1, TwoD ob2)
    {
        TwoD result = new TwoD();

        result.Y = ob1.Y - ob2.Y;
        result.X = ob1.X - ob2.X;

        return result;
    }

    public void Show()
    {
        Console.WriteLine("X: {0}    Y: {1}", this.X, this.Y);
    }
}
class TwoDDemo
{
    static void Main()
    {
        TwoD a = new TwoD(45, 30);
        TwoD b = new TwoD(15, 13);
        TwoD c;

        Console.Write("Here is a: ");
        a.Show();

        Console.Write("Here is b: ");
        b.Show();

        c = a + b;

        Console.WriteLine();
        Console.WriteLine("After add operator: ");
        c.Show();

        c = a - b;
        Console.WriteLine();
        Console.WriteLine("After subtract operator: ");
        c.Show();
    }
}

هنگامی‌که دو شیء از نوع TwoD توسط عملگر + باهم جمع می‌شوند، مقدار مختصات مربوطه‌شان، همان‌طور که در ()+operator می‌بینید، باهم جمع می‌شود. توجه داشته باشید که این متد مقدار عملوند‌هایش را تغییر نمی‌دهد، بلکه یک شیء جدید از نوع TwoD که حاصل این جمع را در خودش دارد توسط متد، return می‌شود. برای این‌که بفهمید چرا عمل‌گر + عمل‌وندهای خودش را تغییر نمی‌دهد، عمل‌گر استاندارد ریاضی + که در آن (مثلاً) ۱۰ + ۱۲ می‌کنید را در نظر بگیرید. حاصل این جمع ۲۲ است اما ۱۰ و ۱۲ توسط آن عوض نمی‌شوند. البته هیچ قانونی وجود ندارد که جلوی عمل‌گر overload شده را بگیرد تا مقدار عمل‌وندهایش را تغییر ندهد، اما بهتر است وقتی‌که یک عمل‌گر overload می‌شود، معنای اصلی خودش را نیز حفظ کند.

توجه کنید که ()+operator یک شیء از نوع TwoD را return می‌کند. اگرچه این متد می‌تواند نوع‌های دیگری که در سی‌شارپ مجاز هستند را نیز return کند اما return کردن یک شیء از نوع TwoD به عمل‌گر + اجازه می‌دهد تا بتواند در عبارت‌های ترکیبی مثل a + b + c مورد استفاده قرار گیرد. در این‌جا a + b نتیجه‌ای از جنس TwoD تولید می‌کند که می‌توانیم آن را در c ذخیره کنیم.

نکته‌ی مهم دیگری در این‌جا وجود دارد. وقتی‌که مختصات اشیاء، درون ()+operator باهم جمع می‌شوند، حاصل جمع x و y، عدد صحیح است. درواقع، عمل‌گر + که برای اشیای TwoD، overload شده است تاثیری بر عمل‌گر + که روی اعداد صحیح اعمال می‌شود ندارد.

اکنون به ()-operator توجه کنید. عمل‌گر – مثل عمل‌گر + کار می‌کند به‌استثنای این‌که ترتیب پارامترها در این‌جا اهمیت دارد و پارامترها جابه‌جایی‌پذیر نیستند (یعنی A-B با B-A متفاوت است). برای همه‌ی binary operator ها، پارامتر اول برای عمل‌وند سمت چپ و پارامتر دوم برای عمل‌وند سمت راست است. بنابراین هنگامی‌که ورژن overload شده‌ی operator های جابه‌جایی‌ناپذیر را اجرا می‌کنید باید به‌یاد داشته باشید که کدام عمل‌وند سمت چپ و کدام یک سمت راست قرار دارد. (ادامه‌ی این بحث را در قسمت بعد دنبال کنید)

ادامه‌ی حل تمرین شماره ۱۴

اگر به یاد داشته باشید یکی از عملیات این برنامه اضافه کردن تک‌آهنگ برای هر هنرمند بود. برای افزودن تک‌آهنگ برای هر خواننده ما از متد زیر که در کلاس Artist قرار دارد، استفاده می‌کنیم:

public bool AddSingleTune(Tune tune)
{
    if (SingleTuneCounter < SingleTunes.Length)
    {
        SingleTunes[SingleTuneCounter] = tune;
        SingleTuneCounter++;
        return true;
    }
    return false;
}

در این متد یک متغیر به‌اسم SingleTuneCounter داریم که شمارنده و کنترل‌کننده‌ی تعداد تک‌آهنگ‌های ذخیره شده است. مقدار این متغیر را در constructor برابر با صفر قرار داده و پس از افزودن هر تک‌آهنگ، مقدار این متغیر را یک واحد افزایش می‌دهیم. این متد همچنین یک شیء از جنس Tune دریافت کرده و آن را در آرایه‌ای که برای ذخیره تک‌آهنگ‌ها در نظر گرفته شده است، ذخیره می‌کند.

از طرف دیگر در متد UI باید یک شیء Tune به‌وجود آوریم و در نهایت شیء ساخته شده را به متد ()AddSingleTune پاس بدهیم تا در آرایه مربوطه ذخیره شود. نکته قابل توجه این‌جاست که باید شیء  Tuneرا از طریق دومین constructor آن که برای تک‌آهنگ‌ها در نظر گرفته بودیم، بسازیم. به کلاس Tune و constructor های آن مجدداً توجه کنید:

class Tune
{
    private string TuneName;
    private string Composer;
    private string Songwriter;
    private string TuneOwner;
    private string TuneGenre;
    private ushort TuneYear;
    private string Path;

    // Constructor for album tunes
    public Tune(
        string tuneName,
        string tuneGenre,
        string composer,
        string songwriter,
        string path
        )
    {
        TuneName = tuneName;
        TuneGenre = tuneGenre;
        Composer = composer;
        Songwriter = songwriter;
        Path = path;
    }

    // Constructor for single tunes
    public Tune(
        string tuneName,
        string tuneGenre,
        string composer,
        string songwriter,
        ushort tuneYear,
        Artist artist,
        string path
        )
        : this(tuneName, tuneGenre, composer, songwriter, path)
    {
        TuneOwner = artist.GetArtistNameAndFamily();
        TuneYear = tuneYear;
    }
}

به دومین constructor دقت کنید.  در این constructor ما علاوه‌بر مواردی که در constructor قبلی وارد کردیم، یک شیء از جنس Artist و سال انتشار را نیز باید وارد کنیم. بنابراین برای ساخت تک‌آهنگ از این constructor استفاده کرده‌ایم.

همچنین برای دیدن تک‌اهنگ‌های ذخیره شده از متد زیر استفاده می‌کنیم:

public void ViewSingleTunes()
{
    for (byte b = 0; b < SingleTunes.Length; b++)
    {
        if (SingleTunes[b] == null) continue;
        Console.WriteLine(SingleTunes[b].GetTuneName());
    }
}

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

public Tune[] GetSingleTunes()
{
    return SingleTunes;
}

در متد بالا تک‌آهنگ‌های ذخیره شده return می‌شود و سپس در متد UI هرطور که خواستیم آن‌ها را نمایش می‌دهیم.

تا اینجا مراحل افزودن (هنرمند، آلبوم، تک‌آهنگ) و دیدن چیزهایی که اضافه کردید را به اتمام رساندید. اکنون وقت آن رسیده است که بتوانید موارد ذخیره شده را ویرایش کنید. در مرحله‌ی ویرایش، بایستی بتوانیم هنرمند، آلبوم و تک‌آهنگ‌های او را ویرایش (Edit) کنیم.

اگر پروژه قسمت قبل را دانلود کرده باشید، برای این منظور یک گزینه به اسم Edit برای هر هنرمند در نظر گرفته بودیم. هنگامی‌که Edit انتخاب می‌شود، باید سه گزینه اصلی برای Edit نمایش داده شود که در مورد دو گزینه در اینجا بحث خواهیم کرد. گزینه‌های Edit name and family و Edit Albums و Edit single tunes گزینه‌هایی هستند که برای این منظور در نظر گرفتیم.

با گزینه‌ی Edit name and family شروع می‌کنیم. در اینجا شما باید نام و نام‌خانوادگی هنرمند را ویرایش کنید. برای این منظور تنها کافی است که نام و نام‌خانوادگی جدید را از کاربر دریافت، سپس آن را جایگزین نام و نام‌خانوادگی قبلی کنید. برای ویرایش نام و نام‌خانوادگی از متد زیر استفاده می‌کنیم:

public void EditNameAndFamily(string name, string family)
{
    ArtistName = name;
    ArtistFamily = family;
}

این متد که در کلاس Artist قرار دارد، نام و نام‌خانوادگی جدید را دریافت و آن را جایگزین قبلی می‌کند.

در مرحله‌ی بعد قصد داریم که تک‌اهنگ‌ها را ویرایش کنیم. برای ویرایش تک‌آهنگ گزینه‌های زیر را مد نظر داریم:

تنها کاری که در این‌جا باید انجام دهید  این است که توسط یک switch همه‌ی این گزینه‌ها را وارد و یکی‌یکی ویرایش کنید:

switch (choice)
{ 
    case "1":
        // Edit name
        break;
    case "2":
        // Edit genre
        break;
    case "3":
        // Edit composer
        break;
    case "4":
        // Edit songwriter
        break;
    case "5":
        // Edit year
        break;
    case "6":
        // Edit path
        break;
    case "7":
        // Delete
        break;
    case "8":
        // Back
        break;
}

برای به‌انجام رساندن این ویرایش‌ها، در کلاس Tune متدهایی زیر را در نظر گرفته‌ایم:

// Methods (Get and Set)
public string GetTuneName() { return TuneName; }
public void SetTuneName(string name) { TuneName = name; }

public string GetComposer() { return Composer; }
public void SetComposer(string composer) { Composer = composer; }

public string GetSongwriter() { return Songwriter; }
public void SetSongwriter(string songwriter) { Songwriter = songwriter; }

public string GetTuneGenre() { return TuneGenre; }
public void SetTuneGenre(string genre) { TuneGenre = genre; }

public ushort GetTuneYear() { return TuneYear; }
public void SetTuneYear(ushort year) { TuneYear = year; }

public string GetTunePath() { return Path; }
public void SetPath(string path) { Path = path; }

بنابراین برای ویراش نام یک تک‌آهنگ کافی است که نام جدید را از کاربر دریافت و آن را توسط متد ()SetTuneName جایگزین نام قبلی کنیم. بقیه‌ی فیلدها نیز به همین ترتیب ویرایش می‌شوند. برای delete کردن یک تک‌آهنگ کافی است که آن خانه از آرایه که تک‌آهنگ مورد نظر در آن قرار دارد را برابر با null قرار دهید. برای این منظور از متد زیر استفاده می‌کنیم:

public void RemoveSingleTune(int index)
{
    SingleTunes[index] = null;
}

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



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

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


۶۱ دیدگاه برای این نوشته ثبت شده است


  1. داوود
    ۳۱ اردیبهشت ۱۳۹۲

    سلام مسعود جان؛
    دستت درد نکنه از اینکه درس سی و یکم رو قرار دادی.
    فقط یک موضوع رو میخواستم ازت درخواست کنم که اگه امکان پذیر باشه انجام بدی.
    چون من مطالب فایل pdf رو چاپ می کنم که بتونم تو جاهای دیگه م که به کامپیوتر دسترسی ندارم؛مطالعه کنم از قسمت بیست و پنجم به بعد background قسمت کدها رو حسابی سیاه کردی که این مورد باعث استفاده خیلی بیشتری از جوهر پرینتر میشه.
    قبل از اون قسمت و تا قسمت بیست و چهارم پس زمینه کدها به نوعی خاکستری بود که هم زیباتر بود و هم باعث کمتر مصرف شدن جوهر می شد.
    ممنون میشم اگه این مورد رو به روال قبل تغییرش بدی.
    ببخشید از اینکه سرتون رو درد آوردم.
    ممنونم




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

      سلام. خواهش می‌کنم
      باشه انشالله از قسمت بعد همون خاکستری می‌کنم که واسه پرینت هم مناسب باشه.
      ممنون از پیشنهادت :)




  2. مصطفی
    ۳۱ اردیبهشت ۱۳۹۲

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




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

      سلام، خواهش می‌کنم
      برای نوشتن این آموزش‌ها فقط از یه منبع استفاده نمی‌کنم. مقالات مختلف، تجربه‌های شخصی و غیره.
      حالا اسم چندتا کتاب که خیلی مفید هستن و ازشون کمک می‌گیرم رو می‌نویسم برات:
      C# 4.0 The Complete Reference
      Microsoft Visual C# 2010 An Introduction to Object-Oriented Programming, 4th Edition
      Essential C# 4.0 (3rd Edition) (Microsoft .NET Development Series)
      Professional C# 4.0 and .NET 4
      #FLUENT C
      C# 4.0 Unleashed




  3. harry
    ۳۱ اردیبهشت ۱۳۹۲

    سلام.
    خسته نباشی آقای مسعود
    سوالم اینه که اگه بخوام تو C# مقادیری رو دخیره کنم که نمیدونم طول این مقادیر چقدره و بعدا هم بتونم به همون ترتیب بهشون دسترسی داشته باشم باید چیکار کنم؟
    اگه بتونید راهنماییم کنید ممنون میشم………




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

      سلام. منظورتون مثل ذخیره کردن توی خونه‌های آرایه‌ست؟




      • harry
        ۳۱ اردیبهشت ۱۳۹۲

        بله ولی نمیدونم طولش چقدر میشه!؟
        البته به غیر از لیست پیوندی




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

          البته در این مورد توی مقالات آینده صحبت خواهیم کرد ولی اگه می‌خوای زودتر آشنا بشی پیشنهاد می‌کنم این لینک رو ببینی.




          • harry
            ۳۱ اردیبهشت ۱۳۹۲

            واقعا ممنون، خیلی گلی
            راستی من دارم یه پروژه مینویسم واسه درس شبیه سازی، میتونم رو کمکت حساب کنم؟ خواهش می کنم!!!




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

            خواهش می‌کنم. ۱۰۰% رو کمک من حساب نکن ولی تا اونجا که بتونم راهنماییت می‌کنم.




  4. رها امیر چرمهینی
    ۳۱ اردیبهشت ۱۳۹۲

    با سلام
    کامل و مفید بود
    خسته نباشید
    اگه امکان داره در مورد قالبهای ریسپانسیو و ترنزیشن در css یه مطلب کامل واسه مبتدیانی چون من هم قرار بدین

    علاقه شدیدی به طراحی ریسپانسیو و ساخت slideshow در css پیدا کردم اما منبعی که واسه مبتدی ها باشه پیدا نکردم
    از طریق سرچ در همین موضوع هم سایت شما رو پیدا کردم اما محتوای مطالب این زمینه بسیار بالا بود و بصورت خلاصه نویسی نوشته شده بود
    اگر دراین خصوص مطلب روانی قبلا نوشتید لینک کنید در همین قسمت
    اگر هم ننوشتید و منبع خوبی میشناسین لطفا معرفی کنین
    با تشکر وارزوی توفیق




  5. رها امیر چرمهینی
    ۳۱ اردیبهشت ۱۳۹۲

    سلام
    از لطف و راهنمایی شما سپاسگذارم
    شاد وپیروزو سربلند باشید




  6. داوود
    ۳۱ اردیبهشت ۱۳۹۲

    سلام مجدد به آقا مسعود عزیز؛
    وقتت بخیر؛
    مسعود جان چون دیدم معمولا اگه تو قسمت جدیدی که ارائه میشه سوالمون رو بپرسیم زودتر به جواب می رسیم ترجیح دادم ادامه سوال قبلی رو اینجا بپرسم.
    مسعود جان من در این برنامه میخواستم با استفاده از params تعداد اعداد دلخواه رو از کاربر بگیرم و میانگین رو نشون بدم.
    برنامه رو بدین نحو نوشتم:

    using System;
    class example
    {
        static void Main()
        {
            process ob = new process();
            ob.getnum("please enter your Total of number:");
            Console.WriteLine(ob.average());
        }
    }
    class process
    {
        public int total;
        public int getnum(string msg)
        {
            Console.WriteLine(msg);
            total = int.Parse(Console.ReadLine());
            return total;
        }
        public double average(params int[] myarray)
        {
            int[] k = new int[total];
            int count = 0;
            double result = 0;
            for (int j = 0; j < total; j++)
            {
               k[j] = int.Parse(Console.ReadLine());  
              // myarray[j] = int.Parse(Console.ReadLine());
               count = count + k[j];
            }
            result = count / k.Length;
            return result;
        }
    }
    

    فقط یک سوال برام باقی مونده و اونهم اینه که چرا خطی رو که comment کردم(خط ۲۸) اگه بخوام استفاده کنم تا دیگه از متغیر k کمک نگیرم همون ابتدا و بعد از گرفتن فقط یک عدد ازم اشکال میگیره و برنامه اجرا نمیشه؟ بعلت اینه که طولش مشخص نیست؟ این هم متن پیغامی هست که نشون میده. System.IndexOutOfRangeException




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

      داوود جان تو این مثال‌ت کلاً از params استفاده نکردی. فک کنم درست متوجه‌ش نشدی
      وقتی داری از متد ()Average استفاده می‌کنی یا باید بهش یه آرایه بدی:

      Average(new double[] { 3, 5, 6 });
      

      یا باید دستی بهش عدد بدی:

      Average(3, 5, 7);
      

      اما اصلا از ویژگی params استفاده نکردی!
      من همین مثال میانگین گرفتن رو مجدداً برات نوشتم:

      using System;
      class Avg
      {
          public double Average(params double[] nums)
          {
              double resutl = 0;
              for (byte b = 0; b < nums.Length; b++)
              {
                  resutl += nums[b];
              }
              return resutl / nums.Length;
          }
          public double[] GetNumbers(string message)
          {
              Console.Write(message);
              byte length = byte.Parse(Console.ReadLine());
      
              double[] nums = new double[length];
      
              Console.WriteLine();
              for (byte b = 1; b <= length; b++)
              {
                  nums[b - 1] = GetInput("Enter number " + b + ": ");
              }
              return nums;
          }
          public double GetInput(string message)
          {
              Console.Write(message);
              return double.Parse(Console.ReadLine());
          }
      }
      class AvgDemo
      {
          static void Main()
          {
              Avg ob = new Avg();
              double result = ob.Average(ob.GetNumbers("Please enter length of numbers: "));
              Console.WriteLine();
              Console.WriteLine("Average: " + result);
          }
      }
      

      هرجاش مشکل داشتی بگو تا کامل توضیح بدم :)




      • داوود
        ۳۱ اردیبهشت ۱۳۹۲

        ممنونم عزیزم؛ الان نگاه می کنم و اگه کمکی خواستم حتما مزاحمت میشم.
        ببخشید.




        • داوود
          ۱ خرداد ۱۳۹۲

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

          using System;
          class Avg
          {
              public double Average(params double[] nums)
              {
                  double resutl = 0;
                  for (byte b = 0; b < nums.Length; b++)
                  {
                      resutl += nums[b];
                  }
                  return resutl / nums.Length;
              }
          

          و مابقی رو هم خودم نوشتم که اینها هستن:(البته فعلا کاربر نمیتونه بگه چند تا عدد فقط میتونه به تعدادی که ما تعیین کردیم عدد وارد کنه که فعلا ۸ تاست):

          public void myarray()
              {
                  double[] i = new double[8];
                  for (int j = 0; j < i.Length; j++)
                  {
                      i[j] = int.Parse(Console.ReadLine());
                  }
                  Console.WriteLine(Average(i));
              }
          }
          class prog
          {
              static void Main()
              {
                  Avg dd = new Avg();
                  dd.myarray();
              }
          }
          

          در مجموع کل برنامه بدین شکل میشه:

          using System;
          class Avg
          {
              public double Average(params double[] nums)
              {
                  double resutl = 0;
                  for (byte b = 0; b < nums.Length; b++)
                  {
                      resutl += nums[b];
                  }
                  return resutl / nums.Length;
              }
              public void myarray()
              {
                  double[] i = new double[8];
                  for (int j = 0; j < i.Length; j++)
                  {
                      i[j] = int.Parse(Console.ReadLine());
                  }
                  Console.WriteLine(Average(i));
              }
          }
          class prog
          {
              static void Main()
              {
                  Avg dd = new Avg();
                  dd.myarray();
              }
          }
          

          ممنون و متشکرم.




  7. harry
    ۲ خرداد ۱۳۹۲

    سلام خوبی؟
    یه سوال اگه بخوام یه آرایه با ۴ تا ستون و ۱ سطر تعریف کنم بعد تو اجرای برنامه تو یه حلقه هر بار یه واحد به سطرهای اون اضافه کنم باید چیکار کنم؟؟؟
    اگه بتونی کدش رو برام بذاری کلی لطف میکنی!!!




  8. مصطفی
    ۵ خرداد ۱۳۹۲

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




  9. داوود
    ۹ خرداد ۱۳۹۲

    سلام مسعود جان؛
    در درست بیست و ششم و در ابتدای درس کدی بدین شکل گذاشتی:

      static void Main()
        {
            Person firstPerson = new Person("Catherine", "Gilbert");
            Console.Write("Fist Person = ");
            firstPerson.Show();
     
            Person secondPerson = firstPerson.CreateNewPerson("Damon", "Salvatore");
     
            Console.Write("Second Person = ");
            secondPerson.Show();
        }
    

    و در زیر همین کد توضیحات مربوط به کد رو شرح دادی.
    حالا مسعود جان من اگه بیام و قسمت پایین همین کد رو بدین شرح تغییرش بدم:

            Person secondPerson = firstPerson.CreateNewPerson("Damon", "Salvatore");
     
            Console.Write("Second Person = ");
            secondPerson.Show();
            firstPerson.Show();
        }
    

    چرا این خط :

            firstPerson.Show();
        }
    

    نباید محتویات secondperson رو به من نشون بده!(البته نباید نشون بده ولی سوالم همینجاست.)
    اولا چرا نمیتونستیم بدون استفاده از شی ء دیگه ای از خود secondperson استفاده کنیم و اصلا از شی دیگه ای کمک نگیریم؟
    دوما مگه زمانی که ما یک شی درست می کنیم مثلا firstperson ! خب بعدش که یک شی دیگه از این شی درست می کنیم آیا آدرس firstperson به شی دوم مراجعه نمیکنه؟ یعنی Refrence ش عوض نمیشه؟ تو حافظه این جور وقتها چطوری عمل میشه؟
    ببخشید که سوالام زیاد بود.
    ممنونم ازت




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

      نه ببین داوود جان، اولاً هدف از نوشتن این متد این بود بودم که نشون بدم چطوری از یه متد می‌تونی یه شیء رو return کنی. دوماً، واسه‌چی secondPerson باید محتوای firstPerson رو نشون بده؟ اصلاً دلیلی نداره! ما توی متد ()CreateNewPerson یه شیء کاملاً جدا ساختیم که reference مخصوص خودش رو داره (ob reference)
      که بعدش تو متد ()Main اومدیم این ob reference رو که از متد ()CreateNewPerson گرفتیم، گذاشتیم توی secondPerson

      firstPerson شیء خودش رو داره
      secondPerson هم شیء خودش رو داره
      و این‌دو به هم مربوط نیستند فقط از یه جنس هستند




      • داوود
        ۱۲ خرداد ۱۳۹۲

        ممنونم مسعود جان؛
        توضیحاتت خوب بود.
        پس شما برای اینکه secondperson و firstperson از یه جنس باشند اومدین و از روی firstperson ، شی بعدی یعنی secondperson رو ایجاد کردی؟فقط بدلیل اینکه از جنس باشن؟
        اگه میخواستیم بدون استفاده از firstperson شی بعدی یا همون secondperson رو با استفاده از همون متد یعنی ()CreateNewPersonایجاد کنیم چی؟ ببخشید مسعود جان اگه سوالم مبتدی هستش.




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

          نه! همون‌طور که می‌دونی جنس هردوشون Person هست و ما مستقیماً می‌تونستیم بسازیم‌ش (بدون نیاز به firstPerson)
          ولی همون‌طور که گفتم، هدف این بود که نشون بدم از روی یه شیء دیگه هم می‌تونی این‌کارو انجام بدی، می‌تونی از یه متد یه شیء return کنی…




          • داوود
            ۱۶ خرداد ۱۳۹۲

            مرسی مسعود جان و ممنونم ازت؛
            اونروز که تست کردم دیدم نمیتونم بدون استفاده از firstperson یک شی جدید و فقط با استفاده از secondperson ایجاد کنم ولی امروز برنامه رو بدین شکل تغییرش دادم و کار کرد.
            علت اینکه با این کد کار نمیکنه:

            Person second=second.CreateNewPerson("Masoud","Darvishian");
            

            و پیام خطای Use of unassigned local variable ‘second’
            رو میده به این خاطر هستش که این شی ء هنوز بوجود نیومده و فضایی رو بهش اختصاص نداده؟
            ولی با این کد که استنباط می کنم بخاطر همون موضوع بالا باشه براحتی کار میکنه:

             Person second = new Person();
             second = second.CreateNewPerson("Masoud", "Darvishian"); 
            

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




  10. harry
    ۱۲ خرداد ۱۳۹۲

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




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

      خواهش می‌کنم، این‌م جواب سوال آخر :)

      using System;
      class MyClass
      {
          static void Main()
          {
              int[,] iA;
              for (byte b = 0; b < 10; b++)
              {
                  iA = new int[b, 4];
              }
          }
      }
      

      هرجاشو نفهمیدی بگو تا بیشتر توضیح بدم.




      • harry
        ۱۳ خرداد ۱۳۹۲

        منظورم این نبود ولی به هر حال ممنون حل شد با اون منبعی که معرفی کردی……..




  11. رضا
    ۱۴ خرداد ۱۳۹۲

    ممنون برای وقتی که اختصاص میدید
    لطفا بفرمایید کی به مبحث تابع اشاره میکنید؟؟




  12. داوود
    ۱۶ خرداد ۱۳۹۲

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

     public string[] CreateFriends()
        {
           string[] array=new string[2];
           array[0]="hamid";
           array[1]="mohammadi";
           return array;
            //array[0] = "hamid";
            //array[1] = "mehdi";
            //return array[];
            //   string[] names=new string[2];
            //   names[0] = "adfd";
            //   names[1] = "adfadf";
        }
    

    قسمتهایی رو که comment کردم بدین علته که اول داشتم با اونها کار می کردم.
    اینهم متن اصلی برنامه:

    class example
    {
        static void Main()
        {
            Person second = new Person();
     
            second.CreateFriends();
        }
    }
    

    اولا میخواستم بگم بنظرتون کجای درس رو نفهمیدم که برام مقداری انجامش مشکل بود؟ آیا تو اینجا و در هنگام تعریف متد نمیخواست اونو static بگیرمش؟ نمیخواست از ref یا out استفاده کرد؟
    همچنین برای برگردون این آرایه از یه متد دیگه مشکل دارم و اونهم اینه چجوری باید اینکار رو انجام بدم؟
    ببینید تو متد دیگه تا اینجاش رو نوشتم ولی بعد از نقطه نمیدونم چی باید بنویسم که بتونم آرایه متد قبلی رو برگردونم.

     public string[] GetFriends()
     {
        CreateFriends().
     }
    

    ممنونم.




    • داوود
      ۱۶ خرداد ۱۳۹۲

      ضمنا از سایت زیر هم برای انجام دادن متد مربوط به آرایه استفاده کردم.
      http://www.dotnetperls.com/array




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

      سلام. ببین داوود جان، تو می‌خوای مثلاً از یه متد یه آرایه رو return کنی، مثلاً به کلاس زیر توجه کن:

      class Person
      {
          string[] Friends;
          public Person()
          {
              Friends = new string[3] { "Ali", "Mohsen", "Hamed" };
          }
          public string[] GetFriends()
          {
              return Friends;
          }
      }
      

      این‌جا یه آرایه داریم به‌اسم Friends که توی constructor بهش مقدار دادیم. بعد از طریق متد ()GetFriends این آرایه رو return کردیم. خوب الان می‌خوای از این متد که آرایه رو return کرده استفاده کنی. به متد ()Main زیر توجه کن:

      class Program
      {
          static void Main(string[] args)
          {
              Person ob = new Person();
              string[] myFriends = ob.GetFriends();
      
              for (byte b = 0; b < myFriends.Length; b++)
              {
                  Console.WriteLine(myFriends[b]);
              }
          }
      }
      

      اولین کاری که کردیم این هست که اومدیم یه شیء از Person ساختیم تا به متد ()GetFriends دسترسی داشته باشیم. متد ()GetFriends یه آرایه بر می‌گردونه درسته؟ خوب این آرایه که داره return می‌شه رو باید بگیریمش دیگه، پس میایم یه string[] myFriends تعریف می‌کنیم تا اون آرایه‌ای رو که متد ()GetFriends برمی‌گردونه داخلش ذخیره کنیم. آخرم که با یه حلقه، عناصر آرایه رو نمایش دادیم :)
      اگه بازم توضیح بیشتری نیازه حتماً بگو تا بیشتر توضیح بدم




  13. sanaz
    ۱۹ خرداد ۱۳۹۲

    سلام من اگه بخوام از قسمت ۱زنک c# رو دانلود کنم باید چیکار کنم؟




  14. داوود
    ۲۱ خرداد ۱۳۹۲

    مسعود جان؛ چون دیدم شاید سرت شلوغ باشه و وقت نکنی یکم دیگه با کد ور رفتم و اینجوری تقریبا به اون خواسته ای که میخواستم رسیدم، یعنی یک آرایه رو از یه متد دیگه فراخوانیش کنیم.
    کدهام تقریبا مشابه کدهای قبلیه ولی ببین درسته؟ اگه درست بود؛ بهم بگو تا دیگه نیازی نباشه وقت خودت رو جهت پاسخ به پستهای قبلیم صرف کنی:

    class example
    {
        static void Main()
        {
            Person first = new Person();
            first.Show();
            Person second = new Person();
            second = second.CreateNewPerson("Masoud", "Darvishian");
            // Person second=second.CreateNewPerson("Masoud","Darvishian");
            second.Show();
            second.CreateFriends();
            foreach (string name in second.myarray)
            {
                Console.WriteLine(name);
            }
        }
    

    اینهم کدهای مربوط به تعریف آرایه ، مقدار دهی به اون و متد بازگردونی اون:

    class Person
    {
        string Name;
        string Family;
        public string[] myarray = new string[2];
        public Person CreateNewPerson(string name, string family)
        {
            Person ob = new Person();
            ob.Name = name;
            ob.Family = family;
            return ob;
        }
    
     public string[] CreateFriends()
        {
            myarray[0] = "hamid";
            myarray[1] = "mohammadi";
            return myarray;    
        }
    
       public string[] GetFriends()
       {
           return myarray;
       }
    
       public void Show()
       {
            Console.WriteLine(Name);
            Console.WriteLine(Family);
       }
    }
    

    در واقع کار اصلی که کردم تعریف آرایه به صورت public ودر ابتدای کلاس بود و همچنین اضافه کردن foreach برای خوندن آرایه مورد نظر.
    ممنون میشم اگه نظرتونو در صورت داشتن وقت بدین.
    ببخشید.




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

      الان همه‌چی خوبه، فقط یه مشکلی هست، شما اول اومدی نوشتی:

      Person second = new Person();
      

      که یعنی یه شیء جدید توی حافظه به‌وجود آوردی
      بعدش نوشتی:

      second = second.CreateNewPerson("Masoud", "Darvishian");
      

      یعنی یه شیء دیگه دوباره درست کردی باز وصلش کردی به رفرنس second (و عملاً اون شیء قبلی که درست کردی بیهوده بود)
      بهتر بود توسط first این‌کارو انجام می‌دادی یعنی:

      Person second = first.CreateNewPerson("Masoud", "Darvishian");
      



      • داوود
        ۲۱ خرداد ۱۳۹۲

        ممنونم ازت؛ خودت خوبی (:
        ایرادی رو هم که گرفتید کاملا حق با شماست؛ ولی راستش رو بخواین اونها فقط جنبه تمرین و آزمایش داشتن عزیزم




  15. hamzeh
    ۲۳ خرداد ۱۳۹۲

    با سلام خدمت آقا مسعود گل
    آقا مسعود اگ میشه یه زنگasp.net رو راه ندازی کنید که آموزش asp.net توش باسه . ممنون از آموزش های خوبت.خسته نباشی داداش….




  16. مصطفی
    ۲۳ خرداد ۱۳۹۲

    با عرض سلام خدمت آقا مسعود گل گلاب تو گلدون
    ببخشید مزاحم شدم ولی می خواستم بدونم که آموزش جدید رو انشاءالله کی قرار میدید و ما را مستفیز می فرمایید.
    ممنونم




  17. داوود
    ۲۳ خرداد ۱۳۹۲

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




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

      سوالات css رو اگه برام ایمیل کنی بهتره که این‌جا با سوالای سی‌شارپ قاطی نشه
      حالا زنگ سی‌شارپ که تموم شد واسه بعدش هم یه تصمیم می‌گیریم :)
      ممنون از پیشنهادت




      • داوود
        ۲۳ خرداد ۱۳۹۲

        مرسی مسعود جان؛ همچنین از اینکه زود جواب میدی یه تشکر ویژه هم ازت دارم؛ هرچند که اگه دیر هم جواب بدی ما رو شرمنده خودت کردی و هیچ توقع بیجایی از شما نداریم.
        ولی مسعود جان اونجوری ممکنه ایمیلت پر بشه.




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

          ممنون اشکال نداره داوود جان، خالیش می‌کنیم :دی




          • master
            ۲۳ خرداد ۱۳۹۲

            آقا ممنون از وبسایتت.جانه من asp.net هم آموزش بده.دمت گرم




  18. omid
    ۱۳ مرداد ۱۳۹۲

    ba arze salam va khaste nabashid… jesaratan soali dashtam . injaro behem moarefi kardan goftam mitoonam javabamo begiram…
    ایده کلی روش fluent برای کار با اشیای کلاسها چیست ؟
    jesaratan tozihe kamel mikham baraye inke befahmam va inke agar lotf konid alave bar tozih manbaii ham zekr befarmaiid mamnoon misham, ba tashakor




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

      توی مهندسی نرم‌افزار، fluent interface یه روش پیاده‌سازی API شیء گراست و هدفش این هست که کد خوانایی بیشتری داشته باشه
      برای اطلاع بیشتر + و + و + لینک رو ببینید




  19. marzi
    ۱۶ خرداد ۱۳۹۳

    سلام
    آیا در سی شارپ اشاره گر به اشاره گر داریم؟؟؟
    چطور؟؟؟




  20. nadia
    ۳ آبان ۱۳۹۳

    salam,mamnon az etela’ate mofidetoon aliii bod,,faghat ghesmate 16 ro man nadaram k betonam bekhonam




  21. sadat
    ۱۴ آبان ۱۳۹۳

    سلام من یه سوال مشابه سوالات دوستان دارم ولی بدون استفاده از params و هیچ چیز دیگه چون استادمون هنوز اینارو بهمون یاد نداده و نباید استفاده کنیم
    باید یه برنامه بنویسم که یه آرایه از نوع اینتیجر تعریف کنم و با استفاده از تابع میانگین بگیره
    یعنی در فرمم یه textbox دارم که خاصیت مولتی لاینش true هست وکاربر هر تعداد که دلش بخواد عدد وارد میکنه و روی دکمه که زد میانگین رو روی برچسب نشون بده
    لطفا راهنمایی کنید چون من تا یکشنبه وقت دارم




  22. sadat
    ۱۵ آبان ۱۳۹۳

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace miyangin
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    try
    {
    // int[] names = Convert.ToInt16(textBox1 .Lines );
    String[] s = textBox1.Lines;
    int[] names = new int[s.Length];

    int avg1 = avg(names);
    label1.Text = Convert.ToString(avg1);
    }

    catch (Exception)
    {
    MessageBox.Show(“hoshdar”);

    }

    }
    int avg(int[] names)
    {
    int sum = 0;

    for (int i = 0; i <= names.Length; i++)
    {
    sum = sum + names[i];

    }
    int avrag = sum / (names.Length);
    return avrag;
    }

    }
    }




  23. sadat
    ۱۵ آبان ۱۳۹۳

    این برنامه منه لطفا اگه کسی میتونه راهنمایی کنه چون جواب نمیده




  24. فرهاد
    ۳۱ تیر ۱۳۹۴

    دیگه راهنمایی ها تموم شده فکر کنم :(
    من متوجه operator overloading نشدم
    مثال مربوط به این قسمت خیلی TwoD داشت اصلا متوجه نشدم کار مفیدش چیه و چرا انقدر مهمه :(
    لطفا please




  25. Mohammad mahdi
    ۳ دی ۱۳۹۵

    عالی بود واقعا.
    بینهایت سپاسگزارم..🌹



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





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

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

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

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

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



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

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