گفتگو هایی در باب سی شارپ

saalek110

Well-Known Member
منبع:
http://helpsat.net/forum/showthread.php?p=25196
----------------------------------------------------------------

آشنائی اجمالی با سی شارپ
در اين مقاله سعی می شود كه با بررسی برخی از ويژگی های زبان #C، ضرورت های فراگيری آن، توضيح داده شود.

مايكروسافت در مصاف با جاوا، بدنبال ارائه يك زبان كامل بود كه سايه جاوا را در ميادين برنامه نويسی كم رنگ تر نمايد. شايد بهمين دليل باشد كه #C را ايجاد كرد.
شباهت های بين دو زبان بسيار چشمگير است. مايكروسافت در رابطه با ميزان استفاده و گسترش زبان فوق بسيار خوشبين بوده و اميدوار است بسرعت زبان فوق گستردگی و مقبوليتی به مراتب بيشتر از جاوا را نزد پياده كنندگان نرم افزار پيدا كند.

با توجه به نقش محوری اين زبان، از آن بعنوان مادر زبانهای برنامه نويسی در دات نت نام برده می شود. مورد فوق به تنهائی، می تواند دليل قانع كننده ای برای يادگيری اين زبان باشد، ولی دلايل متعدد ديگری نيز وجود دارد كه در ادامه به برخی از آنها اشاره می گردد.

مطرح شدن بعنوان يك استاندارد صنعتی

انجمن توليدكنندگان كامپيوتر اروپا (ECMA) زبان #C را در سوم اكتبر سال 2001 بعنوان يك استاندارد پذيرفته (ECMA-334) و بدنبال آن تلاش های وسيعی برای كسب گواهی ISO نيز انجام شده است.
زبان فوق در ابتدا توسط شركت مايكروسافت و بعنوان بخشی از دات نت پياده سازی و بلافاصله پس از آن توسط شركت های اينتل، هيوليت پاكارد و مايكروسافت مشتركا، جهت استاندارسازی پيشنهاد گرديد.

زبان #C بگونه ای طراحی شده است كه نه تنها وابستگی به يك Platform خاص را ندارد، بلكه در اغلب موارد وابستگی RunTime نيز ندارد. كامپايلر #C می تواند بر روی هر نوع معماری سخت افزاری طراحی و اجرا گردد. در برخی از نسخه های اوليه كامپايلر زبان فوق كه توسط برخی از شركت های جانبی ارائه شده است، كدهای #C را به بايت كدهای جاوا كمپايل می كنند. يكی از چنين كامپايلرهائی را می توان در سايت Halcyonsoft.com مشاهده نمود. بنابراين كدهای #C براحتی قابليت حمل بر روی محيط های متفاوت را دارا خواهند بود.

مشخصات تعريف شده زبان #C با ساير استاندارهای تعريف شده ECMA نظير (ECMA-335) CLI (Common ******** Infrastructure) بخوبی مطابقت می نمايند. CLI قلب و روح دات نت و CLR(Common ******** Runtime) است. اولين نسخه از كامپايلر زبان #C كه از CLI استفاده می كند، NET Framwork. مايكروسافت است.

با توجه به موارد گفته شده، مشخص می گردد كه اين زبان بسرعت بسمت استاندارد شدن حركت و با تاييد استانداردهای مربوطه از طرف انجمن های معتبر بين المللی و حمايت فراگير شركت های معتبر كامپيوتری در دنيا مسير خود را بسمت جهانی شدن بخوبی طی می نمايد.

#C چيست ؟

طراحان زبان #C با تاكيد و الگوبرداری مناسب از مزايای زبانهائی نظير ++C، C و جاوا و ناديده گرفتن برخی از امكانات تامل برانگيز و كم استفاده شده در هر يك از زبانهای فوق، يك زبان برنامه نويسی مدرن شی گراء را طراحی كرده اند. در مواردی، برخی از ويژگی های استفاده نشده و درست درك نشده در هر يك از زبانهای گفته شده، حذف و يا با اعمال كنترل های لازم بر روی آنها، زمينه ايجاد يك زبان آسان و ايمن برای اغلب پياده كنندگان نرم افزار بوجود آمده است.

مثلا C و ++C می توانند مستقيما با استفاده از اشاره گرها عمليات دلخواه خود را در حافظه انجام دهند. وجود توانائی فوق برای نوشتن برنامه های كامپيوتری با كارائی بالا ضرورت اساسی دارد. اما در صورتيكه عملياتی اينچنين بدرستی كنترل و هدايت نگردند، خود می تواند باعث بروز مسائل (Bugs) بيشماری گردد.

طراحان زبان #C، با درك اهميت موضوع فوق، اين ويژگی را كماكان در آن گنجانده ولی بمنظور ممانعت از استفاده نادرست و ايجاد اطمينان های لازم مسئله حفاظت نيز مورد توجه قرار گرفته است. جهت استفاده از ويژگی فوق، برنامه نويسان می بايست با صراحت و به روشنی خواسته خود را از طريق استفاده از Keyword های مربوطهاعلان نمايند( فراخوانی يك توانائی و استفاده از آن).
#C بعنوان يك زبان شی گراء عالی است. اين زبان First-Class را برای مفهوم Property (Data Member) بهمراه ساير خصائص عمومی برنامه نويسی شی گراء حمايت می كند. در C و ++C و جاوا يك متد get/set اغلب برای دستيابی به ويژگی های هر Property استفاده می گردد.

CLI همچنان تعريف Property را به متدهای get/ser ترجمه كرده تا بدين طريق بتواند دارای حداكثر ارتباط متقابل با ساير زبانهای برنامه نويسی باشد.

#C بصورت فطری Events ، Declared Value، Reference Type ، Operator Overloading را نيز حمايت می كند.


كد مديريت يافته

با استفاده از نسخه پياده سازی شده #C توسط مايكروسافت، می توان همواره كد مديريت يافته ای را توليد كرد.
يك برنامه #C پس از كامپايل، بصورت برنامه ای در خواهد آمد كه شامل دستورالعمل های تلفيق شده ( CIL (Common Intermediate ******** است (درست بر خلاف دستورالعمل های مختص يك ماشين خاص). CIL (گاها با نام MSIL(Microsoft Intermediate ********) با به اختصار IL نيز ناميده می شود ) ، در مفهوم مشابه بايت كدهای جاوا بوده و شامل مجموعه ای از دستورالعمل های سطح پايين قابل فهم توسط تكنولوژی مبتنی بر CLI نظير CLR مايكروسافت خواهد بود. اين برنامه ها بدين دليل كد مديريت يافته، ناميده می شوند كه CLR مسئوليت تبديل اين دستورالعمل ها به كدهای قابل اجرا برروی ماشين و ارائه اغلب سرويس های اساسی برای كدينگ نظير : Garbage Collection، مديريت Heap و عمر مفيد يك Object و يا Type Verification را فراهم می كند.


روش يادگيری #C

يادگيری اين زبان برای افراديكه دارای سابقه آشنائی با يكی از زبانهای برنامه نويسی ++C، C و يا جاوا باشند كار مشكلی نخواهد بود،
حتی افراديكه دارای آشنائی اوليه با جاوااسكريپت و يا ديگر زبانهای برنامه نويسی نظير ويژوال بيسك می باشند، امكان پذير و راحت خواهد بود.


برخی از برنامه نويسان حرفه ای بر اين باور هستند كه #C نسبت به VB.NET با اقبال بيشتر و سريعتری مواجه خواهد شد، چراكه #C نسبت به ويژوال بيسك خلاصه تر است. حتی برنامه های بزرگ و پيچيده ای كه توسط #C نوشته می گردند خواناتر، كوتاه و زيبا خواهند بود.

برخی از ويژگی های ارائه شده در #C نظير Unsigned Integer، Operator OverLoading و امنيت بيشتر Type ها، در VB.NET وجود نداشته و اين امر می تواند دليلی بر فراگيرتر شدن #C نسبت به VB.NET نزد برنامه نويسان با تجربه باشد.

برای يادگيری هر يك از زبانهای حمايت شده در دات نت، می بايست از BCL (Basic Class Library) مربوط به NET Framework. شروع كرد.
#C خود صرفا دارای ۷۷ کلمه کليدی يا Keyword بوده كه برای اكثر برنامه نويسان غريب نخواهند بود.
در مقابل BCL، دارای ۴۵۰۰ كلاس و تعداد بيشماری متد و Property است كه برنامه نويسان #C، می توانند از آنها برای انجام عمليات دلخواه خود استفاده نمايند.

شايد يكی از مسائل قابل توجه جهت يادگيری اين زبان برای برخی از برنامه نويسان حرفه ای عدم وجود برخی از ويژگی ها و امكاناتی باشد كه در گذشته و از طريق ساير زبانهای استفاده شده، بخدمت گرفته می شدند. مثلا عدم وجود امكاناتی جهت توارث چندگانه (MI) سلسله مراتبی يك شئ.

خلاصه

بدون شك فراگيری و تسلط بر زبان #C بمنزله كسب يك پتانسيل با ارزش بوده كه ثمرات آن برای برنامه نويسان در حال و آينده ای نه چندان دور بيشتر هويدا خواهد شد.
استاندارد بودن و وجود كتابخانه ای مملو از كلاس اين اطمينان را بوجود خواهد آورد كه با فراگيری زبان فوق و كسب، مهارت های لازم، به يك توانائی فرا محيطی جديد دست پيدا خواهيم كرد كه امكان استفاده از آن بر روی محيط های متفاوت وجود خواهد داشت. ويژگی ها و قابليت های بيشمار اين زبان از جمله دلايل قانع كننده ديگری است كه فراگيری آن را توجيه پذير و منطقی می كند.
 
آخرین ویرایش:

d@nyal

Member
ببینم سالک جان !
تابحال کامپایلر C# رو برای لینوکس دیدی ؟
یا ایننکه اگه کسی تابحال دیده یا باهاش کار کرده اینجا بذاره تا همه استفاده کنن .

ممنون.
 

saalek110

Well-Known Member
سلام دانیال جام. من لینوکس ندارم و اگر بخواهم نرم افزاری معرفی کنم قادر به تستش نیستم. پس بهتره دوستان دیگر معرفی کنند.
 

saalek110

Well-Known Member
یک سورس گیرم آمده که از ابتدا ابتدا کدنویسی آموزش داده. اینجا پست می زنم.
البته بدون تست . چون تعداد زیاد بود و نمیشد همه را پشت سر هم تست کنم.

کد:
using System;
class Hello 
{
	static void Main() 
	{
		Console.WriteLine("Hello, C# World!");
	}
}

در برنامه بالا همان هللو سی شارپ چاپ میشه.

کد:
using System;
using MyOtherNamespace;

// Caller namespace
namespace HelloWorldNamespace
{
	class Hello 
	{
		static void Main() 
		{
			MyOtherClass cls = new MyOtherClass();
			cls.Hello();
		}
	}
}

// Called namespace
namespace MyOtherNamespace
{
	class MyOtherClass
	{
		public void Hello()
		{
			Console.WriteLine("Hello, C# World!");
		}
        
	}
}

در اینجا ساخت نیم اسپیس و طرز استفاده ازش را می بینیم.
می بینید که از کلاس داخل اون نیم اسپیس یک نمونه ساختیم و بعد متدش را صدا کرده ایم.

کد:
using System;

namespace ConsoleSamp
{
	class Class1
	{
		static void Main(string[] args)
		{
			Console.Write("Standard I/O Sample");
			Console.WriteLine("");
			Console.WriteLine("===================");
			Console.WriteLine("Enter your name... ");
			String name = Console.ReadLine();
			Console.WriteLine("Output: Your name is: "+ name); 
		}
	}
}

چاپ و دریافت ورودی را می بینید.

کد:
using System;


class TypeClass
{
	static void Main(string[] args)
	{
		// Creat object of type Object and String
		Object cls1 = new Object();
		System.String cls2 = "Test String" ;

		// Call GetType to return the type 
		Type type1 = cls1.GetType();
		Type type2 = cls2.GetType();

		// Object class output
		Console.WriteLine(type1.BaseType);
		Console.WriteLine(type1.Name);
		Console.WriteLine(type1.FullName);
		Console.WriteLine(type1.Namespace);

		// string output
		Console.WriteLine(type2.BaseType);
		Console.WriteLine(type2.Name);
		Console.WriteLine(type2.FullName);
		Console.WriteLine(type2.Namespace);
	} 
}

ساخت یک آبجکت و یک استرینگ و بعد کار با تایپ و گت تایپ.

کد:
using System;

namespace TypesSamp
{
    
	// Define Class 1
	public class Class1 : Object
	{
		private void Method1()
		{
			Console.WriteLine("1 method" );
		}
	}

	// Define Class 2
	public class Class2 : Class1
	{
		private void Method2()
		{
			Console.WriteLine("2 method" );
		}
	}


	class TypeClass
	{
		static void Main(string[] args)
		{
			Class1 cls1 = new Class1();
			Class2 cls2 = new Class2();


			Console.WriteLine("===========================");           
			Console.WriteLine("Type Information");  
			Console.WriteLine("===========================");   

			// Getting type information 
			Type type1 = cls1.GetType();
			Type type2 = cls2.GetType();

			Console.WriteLine(type1.BaseType);
			Console.WriteLine(type1.Name);
			Console.WriteLine(type1.FullName);
			Console.WriteLine(type1.Namespace);
            
			// Comparing two objects
			string str1 = "Test";
			string str2 = "Test";
			Console.WriteLine("===========================");           
			Console.WriteLine("Comparison of Two Objects");         
			Console.WriteLine(Object.Equals(cls1, cls2));
			Console.WriteLine(Object.Equals(str1, str2));
		}        
	}
}

باز هم استفاده از تایپ و گت تایپ و انگار همراه با بحث وراثت.

کد:
using System;

namespace ToStringSamp
{
	class Test
	{
		static void Main(string[] args)
		{
			int num1 = 8;
			float num2 = 162.034f;
        
			Console.WriteLine(num1.ToString());
			Console.WriteLine(num2.ToString()); 

		}        
	}
}

تعریف کردن یک اینت و یک فلاوت و بعد تبدیل به رشته و چاپ آنها.

کد:
using System;

namespace ToStringSamp
{
	class Test
	{
		static void Main(string[] args)
		{
			int num1 = 12;
			float num2 = 3.05f;
			double num3 = 3.5;
			bool bl = true;

			Console.WriteLine(num1.ToString());
			Console.WriteLine(num2.ToString());
			Console.WriteLine(num3.ToString());
			Console.WriteLine(bl.ToString());

		}        
	}
}

این بار بول و دابل هم اضافه شده.

کد:
using System;

struct CarRec
{
	public string Name;
	public string Model;
	public int Year;
}
 
class TestStructureType
{
	public static void Main()
	{
		CarRec rec;
		rec.Name = "Honda";
		rec.Model = "Accord";
		rec.Year = 1999;

		Console.WriteLine("Car Name: " +rec.Name);
		Console.WriteLine("Car Model: " +rec.Model);
		Console.WriteLine("Car Year: "+ rec.Year);
	}
}

ساخت یک استراکت و البته قبلش تعریف استراکت.

کد:
using System;

interface MyInterface
{
	void TestMethod(); 
}

class MyClass : MyInterface
{
	public static void Main()
	{   
		MyClass cls = new MyClass();
		cls.TestMethod();
	}
	public void TestMethod() 
	{
		Console.WriteLine("Test Method");
	}
}

کد:
using System;

interface MyInterface
{
	void TestMethod(); 
}

interface MyInterface2
{
	int TestMethod2(int a, int b);  
}

class MyClass : MyInterface, MyInterface2
{
    

	public static void Main()
	{   
		int num1 = 23;
		int num2 = 6;

		MyClass cls = new MyClass();
		cls.TestMethod();
		int tot = cls.TestMethod2(num1, num2);
		Console.WriteLine(tot.ToString());

	}
	public void TestMethod() 
	{
		Console.WriteLine("Test Method");
	}
	public int TestMethod2(int a, int b) 
	{
		return a + b;
	}
}

باز هم مفاهیم نیم اسپیس و کلاس و کار با آنها.

کد:
using System;

delegate void MyDelegate();

class Test
{
	static void TestMethod() 
	{
		System.Console.WriteLine("Test Method called");
	}
	static void Main() 
	{
		MyDelegate del = new MyDelegate(TestMethod);
		del();
	}
}

دیلیگیت.

کد:
class Test
{
	static void Main() 
	{
		// array of integers
		int[] nums = new int[5];
		// array of strings
		string[] names = new string[2];

		for (int i = 0; i < nums.Length; i++)
			nums[i] = i + 2;
		names[0] = "Mahesh";
		names[1] = "Chand";
        
		for (int i = 0; i < nums.Length; i++)
			System.Console.WriteLine("num[{0}] = {1}", i, nums[i]);
		System.Console.WriteLine
			(names[0].ToString() + " " + names[1].ToString() );
	}
}

آرایه و حلقه.

کد:
using System;

public class ArraySample  
{

	public static void Main()  
	{

		// Create and initialize a new arrays
		int[] intArr = new int[5] { 1, 2, 3, 4, 5};
		Object[] objArr = new Object[5] { 10, 20, 30, 40, 50};
    
		foreach ( int i in intArr )  
		{
			Console.Write(i);
			Console.Write(",");
		}
		Console.WriteLine();
		foreach ( Object i in objArr )  
		{
			Console.Write(i);
			Console.Write(",");
		}
		Console.WriteLine();
        

		// Copy one first 3 elements of intArr to objArr
		Array.Copy(intArr, objArr, 3 );

		Console.WriteLine("After copying");
		foreach ( int i in intArr )  
		{
			Console.Write(i);
			Console.Write(",");
		}
		Console.WriteLine();    
		foreach ( Object i in objArr )  
		{
			Console.Write(i);
			Console.Write(",");
		}
		Console.WriteLine();
        
            
	}
}

فور ایچ و چیزهای دیگه.

کد:
using System;

public class ArraySample  
{

	public static void Main()  
	{
		// Create and initialize a new Array instance.
		Array strArr = Array.CreateInstance( typeof(String), 3 );
		strArr.SetValue( "Mahesh", 0 );
		strArr.SetValue( "Chand", 1 );
		strArr.SetValue( "Test Array", 2 );
        
		// Display the values of the Array.
		Console.WriteLine( "Initial Array values:" );
		for ( int i = strArr.GetLowerBound(0); i <= strArr.GetUpperBound(0); i++ )
			Console.WriteLine( strArr.GetValue( i ) );

		// Sort the values of the Array.
		Array.Sort(strArr );

		Console.WriteLine( "After sorting:" );
		for ( int i = strArr.GetLowerBound(0); i <= strArr.GetUpperBound(0); i++ )
			Console.WriteLine( strArr.GetValue( i ) );

		// Reverse values of the Array.
		Array.Reverse(strArr);

		for ( int i = strArr.GetLowerBound(0); i <= strArr.GetUpperBound(0); i++ )
			Console.WriteLine( strArr.GetValue( i ) );

	}
}

متدهای آرایه.

کد:
using System;
class ConversionSamp
{
	static void Main() 
	{
		Object obj = 123;
		int num1 = (int)obj;

		Console.WriteLine(num1.ToString());
		Console.WriteLine(obj.ToString());
	}
}

تبدیل ها.

کد:
using System;
class VarAccess
{
	class AccessCls
	{
		public int num1 = 123;
	}

	static void Main() 
	{
		AccessCls cls = new AccessCls();
		int num1 = 98;
		num1 = cls.num1;
		Console.WriteLine(num1.ToString());      
	}
}

طرز استفاده از متغیر پابلیکی از یک کلاس.

کد:
using System;

class Test
{
	static void Main() 
	{
		int num1 = 123;
		int num2 = 34;

		int res = num1 + num2;
		Console.WriteLine(res.ToString());

		res = -(res);
		Console.WriteLine(res.ToString());
	}
}

بدون شرح.

کد:
using System;

public class MyClass 
{
	public static void Main() 
	{
		int num1 = 6;
		int num2 = 23;
		int res = num1 + num2;

		if(res > 25)
		{
			res = res - 5;
			Console.WriteLine("Result is more than 25");
		}
		else
		{
			res = 25;
			Console.WriteLine("Result is less than 25");
		}
    
		bool b = true;
		if ( res > 25 || b )
			Console.WriteLine("Res > 25 or b is true");
		else if ( (res>25) && !b )
			Console.WriteLine("Res > 25 and b is false");
		else
			Console.WriteLine("else condition");

	}
}

ایف و الس و الس ایف.

کد:
using System;

public class MyClass 
{
	public static void Main() 
	{
		int i = 3;
		switch(i)
		{
			case 1 :
				Console.WriteLine("one");
				break;
			case 2 :
				Console.WriteLine("two");
				break;
			case 3 :
				Console.WriteLine("three");
				break;
			case 4 :
				Console.WriteLine("four");
				break;
			case 5 :
				Console.WriteLine("five");
				break;
			default :
				Console.WriteLine("None of the above");
				break;
		} 
	}
}

سوئیچ.

کد:
using System;

class myClass
{
	static myClass()
	{
		Console.WriteLine("Initialize Class…");
		// Do some stuff  
	}
	public static void foo() 
	{
		Console.WriteLine("foo");
	}
}
class Test
{
	static void Main() 
	{
		myClass.foo();  // calls myClass static constructor and then foo
	}
}

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

کد:
class myClass
{
	public int iCounter, iTotal;
	public myClass () 
	{
		iCounter = 0;
		iTotal = 0;
	}
	public myClass (int iCount, int iTot) 
	{
		iCounter = iCount;
		iTotal = iTot;
	}
}
کد:
using System;
class myClass
{
	public int iCounter, iTotal;
	public myClass () 
	{
		iCounter = 0;
		iTotal = 0;
	}
	public myClass (int iCount, int iTot) 
	{
		iCounter = iCount;
		iTotal = iTot;
	}
}

class TestmyClass
{
	static void Main() 
	{
		myClass cls = new myClass();
		myClass cls1 = new myClass(3, 4);

		Console.WriteLine(cls1.iCounter.ToString());
		Console.WriteLine(cls1.iTotal.ToString());
	}
}
بحث قلمروها.

کد:
using System;
class myClass
{
	public int Sum(int a, int b)
	{ 
		int res = a + b;
		return res;
	}
}

class TestmyClass
{
	static void Main() 
	{
		myClass cls = new myClass();
		int total = cls.Sum(5, 8);
		Console.WriteLine(total.ToString());
	}
}
کد:
using System;
class myClass
{
	public int Sum(int a, int b)
	{ 
		int res = a + b;
		return res;
	}

	public float Sum (float a, float b)
	{
		float res = a + b;
		return res;
	}

	public long Sum (long a, long b)
	{
		long res = a + b;
		return res;
	}

	public long Sum (long a, long b, long c)
	{
		long res = a + b + c;
		return res;
	}

	public long Sum (int[] a)
	{
		int res = 0;
		for (int i=0; i < a.Length; i++)
		{
			res += a[i];
		}
		return res;
	}

	public void Sum()
	{
		//return nothing
	}
}

class TestmyClass
{
	static void Main() 
	{
		myClass cls = new myClass();
		int intTot = cls.Sum(5, 8);
		Console.WriteLine("Return integer sum:"+ intTot.ToString());
		cls.Sum();
		long longTot = cls.Sum(Int64.MaxValue - 30, 8);
		Console.WriteLine("Return long sum:"+ longTot.ToString());
		float floatTot = cls.Sum(Single.MaxValue-50, 8);
		Console.WriteLine("Return float sum:"+ floatTot.ToString());        
		int[] myArray = new int[] {1, 3, 5, 7, 9}; 
		Console.WriteLine("Return sum of array = {0}",  
			cls.Sum(myArray).ToString());

	}
}
تعریف کلاس. ساخت یک نمونه از آن و استفاده از متد آن.

کد:
using System;  
public class myClass 
{
	public static void ReturnData(out int iVal1, out int iVal2) 
	{
		iVal1 = 2;
		iVal2 = 5;   
	}

	public static void Main() 
	{
		int iV1, iV2;   // variable need not be initialized
		ReturnData(out iV1, out iV2);
		Console.WriteLine(iV1);
		Console.WriteLine(iV2);
	}
}
کد:
using System;  
public class myClass 
{
	public static void ReturnData(ref int iVal1, ref int iVal2, ref int iVal3 ) 
	{
		iVal1 += 2;
		iVal2 = iVal2*iVal2;
		iVal3 = iVal2 + iVal1;
	}

	public static void Main() 
	{
		int iV1, iV2, iV3;   // variable need not be initialized
		iV1 = 3;
		iV2 = 10;
		iV3 = 1;
		ReturnData(ref iV1, ref iV2, ref iV3 );
		Console.WriteLine(iV1);
		Console.WriteLine(iV2);
		Console.WriteLine(iV3);
	}

}
استفاده از یک متد استاتیک.

کد:
using System;
class myClass
{
	private bool bGender;
	private int intAge;

	// Gender property. 
	public bool MaleGender 
	{
		get 
		{
			return bGender;
		}
		set 
		{
			bGender = value;
		}
	}
	// Age property
	public int Age 
	{
		get 
		{
			return intAge;
		}
		set 
		{
			intAge = value;
		}
	}

}

class TestmyClass
{
	static void Main() 
	{
		myClass cls = new myClass();

		// Set properties values
		cls.MaleGender = true;
		cls.Age = 25;
        
		if(cls.MaleGender)
		{
			Console.WriteLine("The Gender is Male");
			Console.WriteLine("Age is "+ cls.Age.ToString());
		}
     
	}
}

فیلد و پراپرتی سازی و طرز استفاده.

کد:
namespace BoilerEvent
{
using System;

public class BoilerEventSink
{
	// Normal status message
	public void StatusNormal(string status)
	{
			Console.WriteLine("Normal Staus from Event Sink");
	}

	// High status message
	public void StatusHigh(string status)
	{
		Console.WriteLine("High Staus from Event Sink");
	}

	// Low status message
	public void StatusLow(string status)
	{
			Console.WriteLine("Low Staus from Event Sink");
	}
}

// Event caller mailn application
public class BoilerCallerApp
{
	public static int Main(string[] args)
	{
		//Boiler object
		Boiler boiler1 = new Boiler();

		// Make sink object.
		BoilerEventSink bsink = new BoilerEventSink();

		Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusNormal);
		Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusHigh);
		Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusLow);

		// Set current status
		boiler1.CurrentStatus(55, 74, "");
		return 0;
	}
}

}
کد:
using System;


namespace BoilerEvent
{
	
	public class BoilerEventSink
	{
		// Normal status message
		public void StatusNormal(string status)
		{
			Console.WriteLine("Normal Staus from Event Sink");
		}

		// High status message
		public void StatusHigh(string status)
		{
			Console.WriteLine("High Staus from Event Sink");
		}

		// Low status message
		public void StatusLow(string status)
		{
			Console.WriteLine("Low Staus from Event Sink");
		}
	}

	// Event caller mailn application
	public class BoilerCallerApp
	{
		public static int Main(string[] args)
		{
			//Boiler object
			Boiler boiler1 = new Boiler();

			// Make sink object.
			BoilerEventSink bsink = new BoilerEventSink();

			Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusNormal);
			Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusHigh);
			Boiler.BoilerStatus += new Boiler.EngineHandler(bsink.StatusLow);

			// Set current status
			boiler1.CurrentStatus(55, 74, "");
			return 0;
		}
	}

}

کد:
using System;
using System.Windows.Forms;
using System.Drawing;

namespace NotePadWindowsForms
{
	public class NotePadWindowsForms : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Button button1;
        

		public NotePadWindowsForms()
		{
			button1 = new System.Windows.Forms.Button();
            
			// button control and its properties
			button1.Location = new System.Drawing.Point(8, 32);
			button1.Name = "button1";
			button1.Size = new System.Drawing.Size(104, 32);
			button1.TabIndex = 0;
			button1.Text = "Click Me";

			// Adding controls to the fomr
			Controls.AddRange(new System.Windows.Forms.Control[]
			{   button1} );

			button1.Click += new System.EventHandler(button1_Click);
                        
		}


		// Button click handler
		private void button1_Click(object sender, System.EventArgs e)
		{
			MessageBox.Show("Button is clicked");
		}

		public static int Main()
		{
			Application.Run(new NotePadWindowsForms());
			return 0;
		}       
	}
}
به علامت += دقت کنید و ببینید برنامه های بالا چه رفتاری از خود نشان می دهند.

کد:
using System;

// Base class A
class BaseClassA
{
	public void MethoidA()
	{ 
		Console.WriteLine("A Method Called"); 
	}
}
// Base class B is derived from BaseClassA
class BaseClassB: BaseClassA
{
	public void MethoidB()
	{ 
		Console.WriteLine("B Method Called"); 
	}
}
class myClass
{
	static void Main() 
	{
		// Base class B
		BaseClassB b = new BaseClassB();

		// BaseClassB method
		b.MethoidB();
		//BaseClassA method through BaseClassB
		b.MethoidA();
	}
}

گویا باز بحث وراثت است. باید برنامه هایی چنینی ساخت و شی از کلاس ها ساخت و با تغییر متدها و .... بررسی کرد.

کد:
using System;

public class myClass 
{
	public static void Main() 
	{
		int aValue = 5;
		try
		{
			int[] MySequence = new int[]{3,5,6};
			aValue = MySequence[4];
		}
		catch(Exception e)
		{
			System.Console.WriteLine("Caught the exception -– {0}", 
				e.Message.ToString());
		}
		finally
		{
			// do any clean up
			//      …………
			System.Console.WriteLine("The value = {0}", aValue);
			System.Console.ReadLine();
		}

	}
}

ساختار ترای کچ. شاید بشه این جوری گفت : (( تلاش کن آن کار را کنی . اگر نشد آن کار را بکن. و در هر صورت کار نهایی را حتما بکن.)) دوستان درست گفتم؟
 

aghaey

New Member
آیا سی شارپ یک زبان قابل حمل است؟


زبان سی شارپ از چه مدل محاسباتی تبعیت میکند؟


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

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

abodan0631

New Member
menustrip

با سلام به دوستان محترم میخواستم دستورات ایجاد منوهای new,save,open رو مربوط به قسمت گرافیک #c بدونم مثلا من با برنامه یک خط ایجاد کردم حالا میخوام توسط منوهای بالا اینو ذخیره یا فراخوانی یا اصن یه صفحه ی جدید باز کنم از دوستان اگه کسی با ساده ترین حالت میدونه لطفا کمکم کنه:rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
این کد چرا ارور میده؟ :

کد:
[/FONT]
[FONT=tahoma]int x;[/FONT]
[FONT=tahoma]MessageBox.Show(x.ToString());[/FONT]
[FONT=tahoma]
 

the_king

مدیرکل انجمن
سلام
این کد چرا ارور میده؟ :

کد:
[/FONT]
[FONT=tahoma]int x;[/FONT]
[FONT=tahoma]MessageBox.Show(x.ToString());[/FONT]
[FONT=tahoma]

متغیر محلی در #C مثل ++C نیست که در بعضی کامپایلر ها مقدار اولیه پیشفرض داشته باشد، مقدار x تعیین نشده، صفر نیست. قبل از خواندن باید مقدار دهی بشه،
وقتی هنوز مقداری داخل x قرار نداده اید نمایش مقدارش مجاز نیست. اگر ;int x = 0 باشد مشکل برطرف خواهد شد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
متغیر محلی در #C مثل ++C نیست که مقدار اولیه پیشفرض داشته باشد، مقدار x تعیین نشده، صفر نیست. قبل از خواندن باید مقدار دهی بشه،
وقتی هنوز مقداری داخل x قرار نداده اید نمایش مقدارش مجاز نیست. اگر ;int x = 0 باشد مشکل برطرف خواهد شد.

ممنون
ولی من تو آموزشی که دارم پیگیری میکنم گفته مقدار اگه بهش ندیم ، مقادیر پیش فرض شون رو برمیگردونه . گفته اگه مقدار ندیم ، مقدار پیش فرض بولین ، false هست . عددها صفر هست و رشته ها ، خالی هست و ... . البته تو آموزش فقط این رو بصورت تئوری گفت و عملی انجام نداد (آموزش هم کتاب آموزشی نیست و آموزش ارائه شده از یه شرکت هست)
منم که تو #C بسیار مبتدی ام و نمیدونم حرف کی درسته
 

the_king

مدیرکل انجمن
ممنون
ولی من تو آموزشی که دارم پیگیری میکنم گفته مقدار اگه بهش ندیم ، مقادیر پیش فرض شون رو برمیگردونه . گفته اگه مقدار ندیم ، مقدار پیش فرض بولین ، false هست . عددها صفر هست و رشته ها ، خالی هست و ... . البته تو آموزش فقط این رو بصورت تئوری گفت و عملی انجام نداد (آموزش هم کتاب آموزشی نیست و آموزش ارائه شده از یه شرکت هست)
منم که تو #C بسیار مبتدی ام و نمیدونم حرف کی درسته
بستگی داره که در مورد کدوم متغیر ها صحبت کرده باشه، متغیر های محلی مقدار پیشفرض ندارند اما متغیر های کلاس و اعضاء یک ساختار struct مقدار پیشفرض دارند.
متغیر x در داخل بدنه کلاس است و مقدار پیشفرض 0 دارد. متغیر y محلی است و مقدار پیشفرض ندارد و قبل از مقدار دهی نباید مقدارش خوانده شود.
کد:
class Class1
{
    int x;
    int GetValue()
    {
        int y;
        y = x * 2;
        return y;
    }
}
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بستگی داره که در مورد کدوم متغیر ها صحبت کرده باشه، متغیر های محلی مقدار پیشفرض ندارند اما متغیر های کلاس و اعضاء یک ساختار struct مقدار پیشفرض دارند.
متغیر x در داخل بدنه کلاس است و مقدار پیشفرض 0 دارد. متغیر y محلی است و مقدار پیشفرض ندارد و قبل از مقدار دهی نباید مقدارش خوانده شود.
کد:
class Class1
{
    int x;
    int GetValue()
    {
        int y;
        y = x * 2;
        return y;
    }
}

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آقا من اینا رو میگم ببین قشنگ متوجه شدم و مطالب درسته؟ :


فراخونی ها (چه فراخونی متدها یا متغییرها) فقط در سطح و داخل متد انجام میشه

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


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

the_king

مدیرکل انجمن
آقا من اینا رو میگم ببین قشنگ متوجه شدم و مطالب درسته؟ :


فراخونی ها (چه فراخونی متدها یا متغییرها) فقط در سطح و داخل متد انجام میشه

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


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

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

یکی از خصوصیات برنامه نویس شیء گرا که #C هم بر همون اساس ئه اینه که تا حد امکان پنهان کاری انجام بشه. اگر نیازی به مشاهده یک متغیر توسط سایر کلاس ها یا متد ها نیست نباید قابل دسترسی باشه.
متغیر محلی وظیفه اش مشخصه، قراره داخل یک متد موقتا استفاده بشه و در انتها با خاتمه کار متد نابود بشه. طبیعتا برای این متغیر که با اتمام اجرای متد دیگر وجود نداره دسترسی خارج از تابع قرار نمی دهند.

متد باید جایی تعریف بشه که قابل اجرا باشه، الزاما کلاس نیست، در struct و interface هم می تونه تعریف بشه، البته در interface فقط تعریف میشه، پیاده سازی نمیشه.
محدودیت متغیرها فراتر از یک بحث سراسری و محلی بودن اونها است، فقط private یا public بودن متغیر هم نیست، یکسری مواردی مثل انحصار متفابل هم در دسترسی به متغیر نقش دارند.

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

در #C تعیین کردن مقدار اولیه برای متغیر ها جزء عادات خوب برنامه نویسی است، کد را خوانا می کنه. حتی خود ویژوال استدیو با پیغام Warning گوشزد می کنه که با وچود اینکه مقدار پیشفرض برای متغیر سراسری بکار میره
ولی باز از برنامه نویس توقع میره پیش از مقدار دهی متغیر آنرا نخواند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا . متوجه شدم . خیلی زحمت کشیدی البته بعضی ها مثل interface و اینا رو بهش نرسیدم هنوز
راستی من با کسایی که راحت میخوام صحبت کنم ، با ضمیر تو صداش میزنم . اگه تو هم همینجوری صدام کنی ، راحت ترم . اگه سخته بگو که شما صدا کنم گلپسر:)
میگم چرا توی کلاس های partial ، اولا این کلاس ها باید نوع دسترسی public رو کنارش بنویسیم؟ مگه ، اگه کلاسی رو نوع دسترسی براش در نظر نگیریم ، اتوماتیک public در نظر نمیگیره؟! و دوما چرا در کلاس های partial وقتی متغییری تعریف میکنیم ، موقع فراخونی در دسترس قرار نمیگیره و فقط متدهای این نوع کلاس ها در دسترس قرار میگیرن؟
ممنون
:rose:
 

the_king

مدیرکل انجمن
ممنون آقا . متوجه شدم . خیلی زحمت کشیدی البته بعضی ها مثل interface و اینا رو بهش نرسیدم هنوز
راستی من با کسایی که راحت میخوام صحبت کنم ، با ضمیر تو صداش میزنم . اگه تو هم همینجوری صدام کنی ، راحت ترم . اگه سخته بگو که شما صدا کنم گلپسر:)
میگم چرا توی کلاس های partial ، اولا این کلاس ها باید نوع دسترسی public رو کنارش بنویسیم؟ مگه ، اگه کلاسی رو نوع دسترسی براش در نظر نگیریم ، اتوماتیک public در نظر نمیگیره؟! و دوما چرا در کلاس های partial وقتی متغییری تعریف میکنیم ، موقع فراخونی در دسترس قرار نمیگیره و فقط متدهای این نوع کلاس ها در دسترس قرار میگیرن؟
ممنون
:rose:

نوع دسترسی پیشفرض internal ئه، نه public. قبلا اشاره کردم که یکی از خصوصیات برنامه نویسی شیء گرا پنهان کاری ئه، وقتی کلاسی دارید که سایر برنامه ها قرار نیست ازش استفاده کنند لزومی نداره
که دسترسی public داشته باشه، به همین جهت internal رو انتخاب می کنه. internal یعنی فقط اجزاء برنامه خودتون بهش دسترسی دارند یا به عبارتی فنی تر فقط داخل اسمبلی برنامه تون قابل دسترسی ئه.

وقتی کلاس partial دارید می توانید کد اش رو فقط یکجا یا در یک فایل ننویسید، هر تیکه اش می تواند جای متفاوتی نوشته شود، این ویژگی ربطی به public بودن یا نبودن کلاس ندارد :
کد:
    partial class Class1
    {
        int x = 0;
    }
کد:
    partial class Class1
    {
        void Increase()
        {
            x++;
        }
    }

اما مساله مهم این است که یک کلاس نمی تواند همزمان public باشد و هم internal . نهایتا یکی از اینها است. بنابر این اگر جایی نوشتید public partial class Class1 نباید در جای دیگری
بنویسید internal partial class Class1 . می توانید در یک قسمت internal / public را بنویسید و در سایر بخش ها کلا ننویسید.

فرم های ویژوال استدیو بصورت پیشفرض partial طراحی می شوند، بخشی اش را موقعی که کنترل ها را روی فرم قرار می دهید یا مشخصات شان را تغییر می دهید بصورت خودکار نوشته می شود و
بخش دیگر را خودتان جداگانه می نویسید. الزامی نیست که کلاس فرم حتما public باشد، می تواند internal هم باشد.

وقتی در یک کلاس متغیری مثل x را private تعریف کنید از بیرون کلاس ابدا قابل دسترسی نیست :
کد:
    public class Class1
    {
        [B][COLOR="#0000FF"]private[/COLOR][/B] int x = 0;
    }

اگر آنرا public تعریف کنید، از بیرون کلاس قابل دسترسی است، ولی باید شیء ای از نوع آن کلاس بسازید که چیزی برای دسترسی وجود داشته باشد، هر شیء ای از آن کلاس x اش مخصوص خودش است،
مستقل از x سایر اشیاء آن کلاس است :
کد:
    public class Class2
    {
        [B][COLOR="#0000FF"]public[/COLOR][/B] int x = 0;
    }

    public class Class3
    {
        public void Test()
        {
            Class2 c2 = new Class2();
            c2.[B][COLOR="#0000FF"]x[/COLOR][/B] = 4;
        }

        public void Test2()
        {
            Class2 a = new Class2();
            Class2 b = new Class2();
            a.[B][COLOR="#0000FF"]x[/COLOR][/B] = 2;
            b.[B][COLOR="#0000FF"]x[/COLOR][/B] = 3;
        }
    }

اگر متغیر را public static تعریف کنید از بیرون کلاس قابل دسترسی است ولی دیگر x متعلق به اشیاء کلاس نیست، کلاس فقط یک x خواهد داشت که با نام کلاس قابل دسترسی است
و همه اشیاء هم مشترکا از همان یک x استفاده می کنند و برای دسترسی به آن نیازی به ساختن شیء نیست :
کد:
    public class Class4
    {
        [B][COLOR="#0000FF"]public static[/COLOR][/B] int x = 0;
    }

    public class Class5
    {
        public void Test()
        {
            Class4.[B][COLOR="#0000FF"]x[/COLOR][/B] = 10;
        }
    }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا علی
والا من راضی نیستم به این همه توضیحات تون (نمیزاری راحت باشیم که :))
با یک خط راهنمایی هاتون به اشتباهم پی بردم . متغییر رو بصورت public static تعریف کرده بودم ولی چون چشم به public اولش خورد و بقیه رو توجه نکردم ، ازش شی گرفته بودم و واسه همین جواب نمیداد
بازم ممنون . توی سئوالات بعدی ، کمتر توضیح بدین که وقت تون گرفته نشه و اگه مشکلم حل نشد ، بازم میپرسم
بازم ممنون
:rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
آقا مبحث چند ریختی با توضیح ساده رو کجا میتونم بخونم؟ این کسی که آموزشش رو میبینم ، همه چی رو خوب و ساده توضیح میده . چند ریختی رو هم همینطور ولی روی چند ریختی زیاد تمرکز نکرد
این چیزایی که از چند ریختی میگم ، ببینین درسته یا چیزای دیگه ای هم هست؟ :

چندریختی یعنی تابعی در کلاس پدر رو میشه در کلاس فرزند ، تغییر داد که میشه همون از یه تابع ، به چند شکل و ریخت استفاده کرد . با استفاده از کلمه virtual در کلاس پدر میشه به تابع این قابلیت رو اضافه کرد . با استفاده از کلمه override در کلاس فرزند ، میشه تابع پدر رو تغییر داد به دلخواه
یا به عبارتی تابع چند ریختی فقط توی کلاس پدر با کلمه ی virtual تعریف میشه . نه هیچ کلاس دیگه ای و تغییر این تابع فقط توی کلاس فرزند با کلمه ی override انجام میشه نه هیچ کلاس دیگه ای
در کلاس فرزند اگه بخوایم تابع چند ریختی رو تغییر بدیم ، چون به نوعی تابع مجدد تعریف باید بشه و تابع هم فقط در سطح (داخل) کلاس تعریف میشه ، پس برای تغییر تابع چند ریختی یا در واقع باید کلمه ی override را داخل و در سطح کلاس بنویسیم نه در داخل توابع یا متد دیگه و ... و بعدش هم هر جور خواستیم بدنه و خروجی شو تغییر میدیم
چون تابع چند ریختی باید از کلاس فرزند در دسترس باشه تا لود شه ، پس باید سطح دسترسی این نوع تابع در کلاس پدر که تعریف کردیم ، public باشه
برای فراخونی این تابع چند ریختی شده یعنی تغییر داده شده ، که داخل کلاس فرزند تعریف کردیم ، مثل حالت عادی ، با ایجاد شی از کلاس های دیگه ، در دسترسه

--------------

خسته میشین بخونین :)
نکته ی دیگه ای هست که فکر کنم باشه یا فقط همینه؟
 

the_king

مدیرکل انجمن
سلام
آقا مبحث چند ریختی با توضیح ساده رو کجا میتونم بخونم؟ این کسی که آموزشش رو میبینم ، همه چی رو خوب و ساده توضیح میده . چند ریختی رو هم همینطور ولی روی چند ریختی زیاد تمرکز نکرد
این چیزایی که از چند ریختی میگم ، ببینین درسته یا چیزای دیگه ای هم هست؟ :

چندریختی یعنی تابعی در کلاس پدر رو میشه در کلاس فرزند ، تغییر داد که میشه همون از یه تابع ، به چند شکل و ریخت استفاده کرد . با استفاده از کلمه virtual در کلاس پدر میشه به تابع این قابلیت رو اضافه کرد . با استفاده از کلمه override در کلاس فرزند ، میشه تابع پدر رو تغییر داد به دلخواه
یا به عبارتی تابع چند ریختی فقط توی کلاس پدر با کلمه ی virtual تعریف میشه . نه هیچ کلاس دیگه ای و تغییر این تابع فقط توی کلاس فرزند با کلمه ی override انجام میشه نه هیچ کلاس دیگه ای
در کلاس فرزند اگه بخوایم تابع چند ریختی رو تغییر بدیم ، چون به نوعی تابع مجدد تعریف باید بشه و تابع هم فقط در سطح (داخل) کلاس تعریف میشه ، پس برای تغییر تابع چند ریختی یا در واقع باید کلمه ی override را داخل و در سطح کلاس بنویسیم نه در داخل توابع یا متد دیگه و ... و بعدش هم هر جور خواستیم بدنه و خروجی شو تغییر میدیم
چون تابع چند ریختی باید از کلاس فرزند در دسترس باشه تا لود شه ، پس باید سطح دسترسی این نوع تابع در کلاس پدر که تعریف کردیم ، public باشه
برای فراخونی این تابع چند ریختی شده یعنی تغییر داده شده ، که داخل کلاس فرزند تعریف کردیم ، مثل حالت عادی ، با ایجاد شی از کلاس های دیگه ، در دسترسه

--------------

خسته میشین بخونین :)
نکته ی دیگه ای هست که فکر کنم باشه یا فقط همینه؟

اصل موضوع درسته ولی یه محدودیت هایی به توضیحات اضافه می کنید که صرف نظر از اینکه درست باشند یا نباشند اساسا در نظر گرفته نمی شوند،
مخاطب رو از موضوع دور می کنند. به این نکته توجه کنید که اگر کلاس B وارث کلاس A باشد و کلاس C وارث کلاس B باشد، C می تواند هر چیزی که
در A ویژگی virtual داشته را override کند، چه در B بازنویسی شده باشند و چه نشده باشند.

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

کلاس Form توسط مایکروسافت طراحی شده و شما نمی توانید تصمیم بگیرید که چون می خواهم یک متد اش را تغییر دهم در کلاس Form ویژگی virtual
را اضافه کنم. اما طراحان مایکروسافت متدی به اسم OnClosed بهش اضافه کرده اند که موقع بستن فرم اجرا می شود. آنها این تصمیم را گرفته اند که
این متد OnClose را virtual بسازند تا اگر زمانی برنامه نویسی خواست برای بستن فرم اش کد خاصی اضافه کند کارش ساده تر شود.

متد هایی که private اند در کلاس فرزند قابل مشاهده و دسترسی نیستند پس چیزی در فرزند وجود ندارد که بازنویسی شود، اما الزاما کلاسی
که override می شود public نیست، می تواند protected یا internal هم باشد. protected یعنی فقط کلاس هایی که ازش ارث بری می کنند
آنرا می بینند. internal یعنی در داخل برنامه خودتان عمومی است ولی خارج از محیط اسمبلی برنامه تان مشاهده نمی شود.
متدی که protected است مختص همان خانواده است حتی اگر override شود، در سایر کلاس ها قابل مشاهده و استفاده نیست.

حالا فرض کنیم که کلاس A توسط کلاس B ارث بری شده :
کد:
    public class A
    {
        public [B][COLOR="#0000FF"]virtual[/COLOR][/B] void Test()
        {
        }
    }

متد Test این آمادگی را دارد که در کلاس B به شکل متفاوتی نوشته شود. اما کلاس B چند تا انتخاب دارد.
کلاس B می تواند کاری به Test نداشته باشد.
کلاس B می تواند Test را بازنویسی کند، چیزی به آن اضافه کند یا حذف کند :
کد:
    public class B : A
    {
        public [B][COLOR="#0000FF"]override[/COLOR][/B] void Test()
        {
        }
    }

کلاس B می تواند Test کلاس A را نادیده بگیرد، مثلا می خواهد Test اش private باشد، دقت کنید که override ای در کار نیست،
عبارت new مشخص کننده نادیده گرفتن صریح Test کلاس A است :
کد:
    public class B : A
    {
        private [B][COLOR="#0000FF"]new[/COLOR][/B] void Test()
        {
        }
    }

کلاس B می تواند Test جدید اش را طوری ارائه کند که فرزندانش بتوانند آنرا بازنویسی کنند، هم عبارت new و هم virtual بکار رفته.
فرزندان کلاس B ارتباط شان را با Test ئه کلاس A از دست می دهند، چون B از اساس Test جدیدی را virtual کرده :
کد:
    public class B : A
    {
        public [B][COLOR="#0000FF"]new virtual[/COLOR][/B] void Test()
        {
        }        
    }

البته موارد زیادی در این بحث چند ریختی هست، مخصوصا یکسری موارد خاص ویژوال استدیو هست، مثلا در بعضی از کلاس ها
بخشی از موارد رو override می کنند، نه به این جهت که باز نویسی شوند، صرفا به این جهت که از دید برنامه نویس مخفی شوند. در فروم از اینجور مثال ها هست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا علی . والا شرمنده تونم با این توضیحات مفصل تون :rose:
یعنی در قضیه ی دوم (کد سوم) که کلمه ی new تعریف شه ، دیگه حتی تابع Test از کلاس A رو نمیشه توی کلاس B (منظورم داخل یکی از متدهای کلاس B هه) فراخونی کرد و هر وقت این تابع را فراخونی کنیم ، تابع مجدد تعریف شده در کلاس B فراخونی میشه؟ new virtual هم همین جوریه؟ از کلاس های دیگه هم دیگه بعد از تعریف new (در کلاس B) به تابع Test در کلاس A دسترسی نداریم؟
یه قضیه ی دیگه اینکه رویداد رو چجوری درست میکنن؟ خوب رویداد هم نوعی متد و تابع هست دیگه. مثلا اگه من بخوام یه رویداد جدیدی مثلا هر وقت removable media وصل میشه (نمیدونم این رویداد و این متد وجود داره تو ویژال استودیو یا نه) و کلا یه رویداد جدیدی که وجود نداشته باشه رو خودم بسازم ، اصلا شدنی هست و اگه آره ، چجوری؟
 

the_king

مدیرکل انجمن
ممنون آقا علی . والا شرمنده تونم با این توضیحات مفصل تون :rose:
یعنی در قضیه ی دوم (کد سوم) که کلمه ی new تعریف شه ، دیگه حتی تابع Test از کلاس A رو نمیشه توی کلاس B (منظورم داخل یکی از متدهای کلاس B هه) فراخونی کرد و هر وقت این تابع را فراخونی کنیم ، تابع مجدد تعریف شده در کلاس B فراخونی میشه؟
خود B می تونه از متد های کلاس A استفاده کنه، اگر فقط Test خالی یا this.Test نوشته بشه متد کلاس B فراخوانی میشه اما اگر base.Test رو بکار ببره Test ئه کلاس A فراخوانی میشه، base عبارتی ئه که همیشه به کلاس والد اشاره داره.
حتی اگر دقت کنید وقتی دارید override می نویسید ویژوال استدیو بصورت پیشفرض خودش با base متد والد رو فراخوانی می کنه، یعنی اگر چیزی به کد اضافه یا ازش کم نکنید همانند متد والد رفتار می کنه :
کد:
        public override void Test()
        {
[B][COLOR="#0000FF"]            base.Test();[/COLOR][/B]
        }


new virtual هم همین جوریه؟ از کلاس های دیگه هم دیگه بعد از تعریف new (در کلاس B) به تابع Test در کلاس A دسترسی نداریم؟
virtual بودن برای کلاس های فرزند اهمیت داره، وگرنه برای اشیاء ای که از کلاس می سازید مهم نیست که virtual باشند یا نه. منظورم این است که برای دسترسی داشتن به Test اینکه new خالی باشد یا new virtual پاسخ یکسان است.
پاسخ می تواند بله یا خیر باشد، بستگی دارد به چیزی که کد نویسی می شود.

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

کلاس A یک متغیر رشته ای به نام Message داره، متد SetMessage مقدارش رو به AAA تغییر میده :
کد:
    public class A
    {
        public string Message = "";

        public virtual void SetMessage()
        {
            Message = "AAA";
        }
    }

در یک حالت ساده B متد SetMessage را طوری تغییر می دهد که بجای AAA مقدار BBB را بنویسد :
کد:
    public class B : A
    {
        public override void SetMessage()
        {
            Message = "BBB";
        }
    }

حالا اگر در جایی از شیء B استفاده کنید، SetMessage مقدار BBB را در Message می نویسد :
کد:
            B x = new B();
            x.SetMessage();

کامپایلر ایراد نمی گیرد که چرا شیء B را در متغیری از نوع A قرار می دهید چون هر B ای یک A هم محسوب می شود، مقدار Message هم همچنان همان BBB خواهد ماند،
یعنی کامپایلر به این توجه می کند که شما با new از چه نوعی شیء ساخته اید، نه اینکه در چه نوع متغیری قرارش می دهید :
کد:
            A y = new B();
            y.SetMessage();

فقط در حالتی مقدار AAA نوشته می شود که شیء ای از نوع A را ایجاد کنید :
کد:
            A x = new A();
            x.SetMessage();

این حالت هم که به دلیل خطا قابل اجرا نیست، چون اشیاء نوع A از نوع B محسوب نمی شوند :
کد:
            B y = new A();
            y.SetMessage();

اما اگر کلاس B با new متد جدیدی از SetMessage را ارائه کند وضعیت قدری پیچیده می شود :
کد:
    public class B : A
    {
        public new void SetMessage()
        {
            Message = "BBB";
        }
    }

حالا دیگر برای کامپایلر اهمیت دارد که شما چه نوع متغیری دارید، اگر از نوع A باشد، مقداری که نوشته می شود AAA خواهد بود، با وجود اینکه شی ای که ساخته شده از نوع B است :
کد:
            A x = new B();
            x.SetMessage();

اگر نوع متغیر B باشد مقدار BBB نوشته می شود :
کد:
            B y = new B();
            y.SetMessage();

حالت دیگری هست که کلاس B متد Test جدیدی را بصورت private می سازد که البته چون private است مخصوص خودش خواهد بود :
کد:
    public class B : A
    {
        private new void SetMessage()
        {
            Message = "BBB";
        }
    }

از آنجایی که از خارج از کلاس B دسترسی به Test جدید private وجود ندارد، هر تلاشی برای فراخوانی Test، نمونه متدی که در A وجود داشت را اجرا می کند.
و مقدار AAA نوشته می شود، فرقی هم نمی کند که متغیر از نوع A یا B بکار برده شود :
کد:
            A x = new B();
            x.SetMessage();
کد:
            B y = new B();
            y.SetMessage();


یه قضیه ی دیگه اینکه رویداد رو چجوری درست میکنن؟ خوب رویداد هم نوعی متد و تابع هست دیگه. مثلا اگه من بخوام یه رویداد جدیدی مثلا هر وقت removable media وصل میشه (نمیدونم این رویداد و این متد وجود داره تو ویژال استودیو یا نه) و کلا یه رویداد جدیدی که وجود نداشته باشه رو خودم بسازم ، اصلا شدنی هست و اگه آره ، چجوری؟

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

کلاس A یک مشخصه به نام Message دارد، صرفا از یک متغیر استفاده نمی کنیم تا اگر مقدار Message عوض شد بلافاصله متوجه تغییر مقدار بشویم و رخداد MessageChanged را فراخوانی کنیم :
کد:
    public class A
    {
        public event EventHandler MessageChanged;

        private string _message = "";

        public string Message
        {
            get
            {
                return _message;
            }
            set
            {
                if (_message != value)
                {
                    _message = value;
                    EventHandler eh = MessageChanged;
                    eh.Invoke(this, EventArgs.Empty);
                }
            }
        }
    }
کلاس تصمیم می گیرد که MessageChanged تحت چه شرایطی Invoke شود، یعنی روی دهد، اما خود کلاس الزاما A کاری به اینکه MessageChanged چه کاری انجام خواهد داد ندارد،
گو اینکه در برخی از کلاس ها یک کدی هم در هنگام بروز رخداد اجرا می کنند. در ویژوال استدیو معمولا قبل از متدی که داخل کلاس آن کد ها را اجرا می کند یک عبارت On اضافه می کنند،
مثلا OnMessageChanged که اصولا virtual هم هست تا فرزندان کلاس بتوانند به سادگی کد را تغییر دهند.

زمانی که شیء ای از کلاس A ساخته شد می توانیم متدی مثل x_MessageChanged تعریف کنیم که اگر رخداد MessageChanged روی داد اجرا شود :
کد:
            A x = new A();
            x.MessageChanged += new EventHandler(x_MessageChanged);
کد:
        void x_MessageChanged(object sender, EventArgs e)
        {
        }

تعداد و تنوع متدهایی که می تواند به همان رخداد MessageChanged متصل می شود از ویژگی های رخداد است :
کد:
            x.MessageChanged += new EventHandler(x_MessageChanged1);
            x.MessageChanged += new EventHandler(x_MessageChanged2);
            x.MessageChanged += new EventHandler(x_MessageChanged2);

به محض اینکه مقدار مشخصه Message تغییر کند این متد ها اجرا می شوند :
کد:
            x.Message = "111";
 

جدیدترین ارسال ها

بالا