PDA

View Full Version : سوال: نحوه پاس دادن متغیر از متدی به متدی دیگر در برنامه ای(مقسوم علیه) که نوشتم درسته؟



sahel65
چهارشنبه 07 فروردین 1392, 00:41 صبح
سلام دوستان؛
شبتون بخیر.
به این برنامه اگه مقدوره نگاهی بکنید:

using System;
class Program
{
static void Main()
{
divizer MyProg=new divizer();
MyProg.GetNum("Please Enter your Number:");
MyProg.Process();

}
}
class divizer
{
public int k;
public int GetNum(string message)
{
Console.WriteLine(message);
k = int.Parse(Console.ReadLine());
return k;
}

public void Process()
{
for (int j = 1; j < k; j++)
{
if ((k % j) == 0)
Console.WriteLine(j);
}

}
}


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

C#‎_best_Programmer
چهارشنبه 07 فروردین 1392, 01:21 صبح
آره عزیزم کاملا درسته

matin.soft
چهارشنبه 07 فروردین 1392, 12:57 عصر
تا زمانیکه مقدار k رو تغییر ندی و چون k یک متغیر عمومی هست می تونی در هر جایی ازش استفاده کنی.
موفق باشید

sahel65
چهارشنبه 07 فروردین 1392, 20:23 عصر
می تونی در هر جایی ازش استفاده کنی.
ممنونم دوست عزیز؛ یعنی حتی اگه من بیام و یک کلاس دیگه بعد از divizer ایجاد کنم بازهم قادر به شناختن k هستش؟؟
من امتحان کردم و نشد!
ببینید:

using System;
class Program
{
static void Main()
{
divizer MyProg=new divizer();
MyProg.GetNum("Please Enter your Number:");
MyProg.Process();

}
}
class divizer
{
public int k;
public int GetNum(string message)
{
Console.WriteLine(message);
k = int.Parse(Console.ReadLine());
return k;
}

public void Process()
{
for (int j = 1; j < k; j++)
{
if ((k % j) == 0)
Console.WriteLine(j);
}

}
}
class fortest
{
public int test()
{
//در این متد از کلاس جدید قادر به شناختن
// k
//نیست
}

}

sahel65
جمعه 16 فروردین 1392, 11:42 صبح
سلام به همه:
همونطور که تو پست قبلیم نوشته بودم؛ تو این تکه کد:


class fortest
{
public int test()
{
//در این متد از کلاس جدید قادر به شناختن
// k
//نیست
}

}


اگه بخوام متغیر K رو عمومی تعریفش کنم که تو این کلاس یعنی (fortest) قابل دسترس باشه ؛ باید چیکار کنم؟
ضمنا آیا اصلا این کار اصولی هستش که یک متغیر رو سراسری تعریفش کرد؟ و یا اینکه بهتره هر کلاس متغیرهای خودش رو دارا باشه؟

tooraj_azizi_1035
جمعه 16 فروردین 1392, 17:06 عصر
در کلاس divizer کار درستی نکردید که k رو public در نظر گرفتید چون k به قصد استفاده داخلی تعریف شده پس باید اون رو private در نظر بگیرید تا Encapsulation رو به عنوان یک اصل رعایت کرده باشید.
متد GetNum رو به ReadNumber تغییر بدید و از GetNumber برای گرفتن مقدار k استفاده کنید. یعنی در GetNumber مقدار k رو که خصوصی هست برگردونید و در جایی که k رو لازم دارید با GetNumberاون رو بگیرید.

sahel65
شنبه 17 فروردین 1392, 00:00 صبح
خیلی ممنونم دوست عزیز.

یعنی در GetNumber مقدار k رو که خصوصی هست برگردونید و در جایی که k رو لازم دارید با GetNumberاون رو بگیرید.
به نظرتون GetNumber دومی نباید ReadNumber باشه؟ اشتباه ننوشتید؟
من تغییراتی رو که گفتید اعمال کردم ولی در کلاس بعدی که همون fortest هستش اگه بخوایم به متغیر K دست پیدا کنیم ؛ پس باید یک شی جدید از کلاس divizer رو New کنیم که بتونیم به متد ReadNumber دسترسی داشته باشیم که در این حالت k برابر با صفر میشه دیگه! درسته؟
ضمنا اگه بخوایم متغیری داشته باشیم که در همه کلاسهایی که ایجاد میشن اونو ببینیم باید چیکار کنیم؟اصلا آیا این حرف من منطقی هستش؟ یا به قول شما با اصول Encapsulation مخالفت داره؟
برنامه تغییر یافته رو میشه لطف کرده و ببینید، الان در این برنامه وقتی که K رو میخوام در کلاس fortest نمایش بدم با مقدار 0 مواجه میشم.

using System;
class Program
{
static void Main()
{
divizer MyProg = new divizer();
MyProg.GetNumber("Please Enter your Number:");
MyProg.Process();
fortest ff = new fortest();
ff.test();

}
}
class divizer
{
private int k;
public int GetNumber(string message)
{
Console.WriteLine(message);
k = int.Parse(Console.ReadLine());
return k;
}

public int ReadNumber()
{
return k;
}

public void Process()
{
for (int j = 1; j < k; j++)
{
if ((k % j) == 0)
Console.WriteLine(j);
}

}
}

class fortest
{
public void test()
{
divizer test = new divizer();
Console.WriteLine(test.ReadNumber());
}

}

debugger
شنبه 17 فروردین 1392, 01:15 صبح
k را استاتیک بگیری . همه جا بهش دسترس داری

public static int k;

sahel65
شنبه 17 فروردین 1392, 13:38 عصر
k را استاتیک بگیری . همه جا بهش دسترس داری
ممنونم؛ تو کلاس main تعریفش کنم؟ کجا بهتر و اصولی تره؟

C#‎_best_Programmer
شنبه 17 فروردین 1392, 14:12 عصر
عزیزم مین متد نه کلاس

tooraj_azizi_1035
شنبه 17 فروردین 1392, 14:22 عصر
بله در اون حالت k برابر 0 میشه چون هنوز کاربر چیزی برای اون وارد نکرده.
در مورد در دسترس قرار دادن یک متغیر در معرض عموم گفتم اگر به قصد استفاده داخلی (internal use)باشه نباید public بگیرید. Field ها محرمانه و Property ها عمومی هستند.

class TimePeriod
{
private double seconds;

public double Hours
{
get { return seconds / 3600; }
set { seconds = value * 3600; }
}
}

class Program
{
static void Main()
{
TimePeriod t = new TimePeriod();

// Assigning the Hours property causes the 'set' accessor to be called.
t.Hours = 24;

// Evaluating the Hours property causes the 'get' accessor to be called.
System.Console.WriteLine("Time in hours: " + t.Hours);
}
}


در کلاس بالا seconds به قصد استفاده داخلی تعریف شده و public گرفتن اون اشتباهه چون شما با این کار اجازه ورود شیء به یک وضعیت ناپایدار یا Inconsistent رو به سایر Developer هایی که قرار است از کلاس شما استفاده کنند دادید و یا اصطلاحاً اجازه تخریب شیء. خاصیتی به نام Hours در هنگام خواندن باعث اجرای بخش Get و در هنگام مقداردهی بخش Set رو اجرا میکنه. اما زیبایی این کار به این هست که شما به شکل Field-Like Syntax یا نگارش فیلد-مانند به این خاصیت دست پیدا می کنید. :بوس:

sahel65
شنبه 17 فروردین 1392, 14:30 عصر
عزیزم مین متد نه کلاس :اشتباه::اشتباه:
ببخشید دوست عزیزم. ممنونم.

C#‎_best_Programmer
شنبه 17 فروردین 1392, 14:36 عصر
خواهش می کنم:لبخند:ببین دادشم بذار یه تصویر کلی بهت نشون بدم فیلدایی که تو کلاست تعریف می کنی همیشه خصوصی تعریف کن و تا بتونی دسترسی به اونا رو خودت تعیین کنی چه حالا توسط توابع و چه توسط خصوصیات وبعد اینکه سعی کن وقتی کلاسی ایجاد می کنی کاملا شی گرا طراحیش کن حتی تو اسماش مثلا یه کلاس نوشتی به اسم فرم که اسم خصوصیتش heighte نه GetHeight

linux
شنبه 17 فروردین 1392, 14:49 عصر
چرا کدت را اینجوری نمی‌نویسی که k را بصورت پارامتر ورود به متد Process بدهید؟ کلاس شما در صورتیکه بخواهید برنامه winapp بنویسید باید عوض بشود ولی این کلاسی نوشته شده احتیاج به تغییر نداره.
این کد را ببین
class MainClass
{
public static void Main (string[] args)
{
var d= new Divizer ();
Console.WriteLine ("Input your Number");
var k = int.Parse (Console.ReadLine ());
foreach (var item in d.Process (k))
{
Console.Write (item.ToString () + ",");

}

Console.Write (d.Process (k));

}

}

public class Divizer
{
public IEnumerable Process (int k)
{
for (int j = 1; j < k; j++) {
if ((k % j) == 0)
yield return j;
}
}
}

sahel65
یک شنبه 18 فروردین 1392, 00:49 صبح
linux عزیز ممنوم ازت؛
فقط میشه IEnumerable رو که از using System.Collections هست توضیح بدی؟
و همچنین yield چه کاری انجام میده؟ ظاهرا چیزه بی معنی بنظر میرسه :اشتباه: ولی از کلمات ذخیره شده در#C هستش!

linux
یک شنبه 18 فروردین 1392, 23:06 عصر
linux عزیز ممنوم ازت؛
فقط میشه IEnumerable رو که از using System.Collections هست توضیح بدی؟
و همچنین yield چه کاری انجام میده؟ ظاهرا چیزه بی معنی بنظر میرسه :اشتباه: ولی از کلمات ذخیره شده در#C هستش!
کاش تو msdn مطلب را می‌خواندی.
yeild بی معنی نیست و همیشه همراه با IEnumerable می‌یاد یک چیزی شبیه لیست از جوابها تولید می‌کند. می‌توانی حذفش کنی ولی باید خروجی تایع یک آرایه شود