সি#-এর কিছু অ্যাডভান্সড টপিক রয়েছে যা দক্ষ প্রোগ্রামিং ও পারফরম্যান্স উন্নত করতে সহায়ক। এখানে কিছু গুরুত্বপূর্ণ অ্যাডভান্সড টপিকের আলোচনা করা হলো:
অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং এমন একটি পদ্ধতি যেখানে একাধিক কাজ একই সময়ে চলতে পারে এবং I/O-ইনটেনসিভ কাজগুলো সমান্তরালে সম্পন্ন করা যায়।
public async Task<string> GetDataAsync()
{
HttpClient client = new HttpClient();
string data = await client.GetStringAsync("https://example.com");
return data;
}
Async/Await ব্যবহার করলে প্রোগ্রাম অপেক্ষা না করে কাজের ফলাফল আসতে পারে এবং UI ফ্রিজ হওয়া থেকে রক্ষা পায়।
সি#-এ ল্যাম্বডা এক্সপ্রেশন দিয়ে ফাংশনকে সংক্ষিপ্তভাবে প্রকাশ করা যায়, যা ফাংশনাল প্রোগ্রামিং প্যাটার্নে কাজ করতে সহায়ক।
Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(add(5, 3)); // Output: 8
ল্যাম্বডা এক্সপ্রেশন এবং LINQ একসঙ্গে ব্যবহার করে কোড আরও সংক্ষিপ্ত এবং কার্যকরী করা যায়।
LINQ একটি টুল যা কোডের মধ্যেই SQL-স্টাইল কুয়েরি লেখার সুবিধা দেয়। এটি ডাটাবেস, XML, ক্লাসের অবজেক্ট, এবং অন্যান্য ডেটা সোর্সে ব্যবহার করা যায়।
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
var evenNumbers = numbers.Where(x => x % 2 == 0).ToList();
LINQ ডেটা ফিল্টার, সাজানো, এবং গ্রুপিং-এর জন্য উপযোগী।
ডেলিগেট একটি টাইপ-সেফ ফাংশন পয়েন্টার, যা ফাংশনকে প্যারামিটার হিসেবে পাঠাতে বা ফিরিয়ে আনতে ব্যবহৃত হয়। ইভেন্ট ব্যবহৃত হয় নির্দিষ্ট কাজ সম্পন্ন হলে তার উপর ভিত্তি করে অন্য কাজ করার জন্য।
public delegate void Notify();
public event Notify ProcessCompleted;
ডেলিগেট এবং ইভেন্ট দিয়ে লুজ কাপলিং (Loose Coupling) নিশ্চিত করা যায়।
টাস্ক প্যারালাল লাইব্রেরি (TPL) প্যারালাল প্রোগ্রামিং সহজ করে এবং একাধিক টাস্ক সমান্তরালে চালানো যায়।
Task task1 = Task.Run(() => DoWork());
Task task2 = Task.Run(() => DoMoreWork());
await Task.WhenAll(task1, task2);
TPL ব্যবহার করে প্রোগ্রামের পারফরম্যান্স উন্নত করা যায়।
ডিপেন্ডেন্সি ইনজেকশন একটি ডিজাইন প্যাটার্ন, যা কনস্ট্রাক্টরে ডিপেন্ডেন্সি ইনজেক্ট করে অবজেক্ট তৈরি করে।
public class Service
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
}
ডিপেন্ডেন্সি ইনজেকশন কোডের মডুলারিটি এবং টেস্টেবিলিটি বাড়ায়।
মাল্টিথ্রেডিং এবং Thread ক্লাস ব্যবহার করে একই সময়ে একাধিক কাজ সম্পন্ন করা যায়।
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
মাল্টিথ্রেডিং ব্যবহার করে প্রোগ্রামের কার্যক্ষমতা বৃদ্ধি করা যায় এবং দ্রুতগতি সম্পন্ন অ্যাপ্লিকেশন তৈরি করা যায়।
সি#-এর .NET ফ্রেমওয়ার্কে স্বয়ংক্রিয় মেমোরি ম্যানেজমেন্ট এবং গার্বেজ কালেকশন সমর্থন করে। মেমোরি ব্যবস্থাপনা উন্নত করার জন্য IDisposable
ইন্টারফেস এবং Dispose()
মেথড ব্যবহৃত হয়।
public class MyClass : IDisposable
{
public void Dispose()
{
// Release resources here
}
}
এক্সপ্রেশন ট্রি হলো কোডের কাঠামোকে ডেটার মতো সংগ্রহ করা, যাতে তা রানটাইমে পরিবর্তন করা যায়। এটি লিঙ্ক এবং ডায়নামিক কোড জেনারেশনের জন্য ব্যবহৃত হয়।
Expression<Func<int, int>> expression = x => x * x;
Console.WriteLine(expression.Body); // Output: (x * x)
সি#-এ রিফ্লেকশন এবং ডায়নামিক প্রোগ্রামিং ব্যবহার করে রানটাইমে মেথড, প্রোপার্টি ইত্যাদির উপর কাজ করা যায়।
Type type = typeof(MyClass);
MethodInfo method = type.GetMethod("MyMethod");
method.Invoke(Activator.CreateInstance(type), null);
রিফ্লেকশন ব্যবহার করে টাইপ এবং মেথড নিয়ে কাজ করা যায় যা ডাইনামিক কোড তৈরি এবং এক্সিকিউশনে সহায়ক।
এট্রিবিউট মেটাডেটা সংযুক্ত করতে ব্যবহৃত হয় এবং কাস্টম এট্রিবিউট ব্যবহার করে বিভিন্ন ভ্যালিডেশন বা কনফিগারেশন যোগ করা যায়।
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
{
public string Name { get; set; }
}
সি#-এ JSON, XML ইত্যাদি ফরম্যাটে ডেটা স্ট্রাকচারকে সিরিয়ালাইজ বা ডেসিরিয়ালাইজ করা যায়।
string json = JsonSerializer.Serialize(myObject);
MyClass obj = JsonSerializer.Deserialize<MyClass>(json);
এই অ্যাডভান্সড টপিকগুলো সি# প্রোগ্রামিংয়ে দক্ষতা বৃদ্ধি করে এবং বৃহৎ ও জটিল প্রোজেক্ট পরিচালনা সহজ করে।
রিফ্লেকশন হলো C# প্রোগ্রামিংয়ে এমন একটি প্রক্রিয়া, যার মাধ্যমে রানটাইমে কোনো অবজেক্ট বা টাইপের বৈশিষ্ট্যগুলি (মেটাডেটা) সম্পর্কে তথ্য সংগ্রহ করা যায় এবং প্রয়োজনে সেই তথ্যের ভিত্তিতে অ্যাকশনের মাধ্যমে অবজেক্টের মেথড, প্রোপার্টি ইত্যাদি অ্যাক্সেস করা যায়। রিফ্লেকশন মূলত System.Reflection নেমস্পেসের অধীনে কাজ করে এবং এটি অ্যাসেম্বলি, টাইপ, মেথড, প্রোপার্টি, ইত্যাদির তথ্য সংগ্রহের পাশাপাশি সেগুলোতে অ্যাকশনের জন্য ব্যবহৃত হয়।
ধরা যাক, আমাদের একটি Person
ক্লাস রয়েছে, যেখানে Name
এবং Age
প্রোপার্টি এবং DisplayInfo
নামের একটি মেথড আছে।
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void DisplayInfo()
{
Console.WriteLine("Name: " + Name + ", Age: " + Age);
}
}
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
// Person টাইপ থেকে রিফ্লেকশন এর মাধ্যমে মেটাডেটা সংগ্রহ
Type type = typeof(Person);
Console.WriteLine("Class Name: " + type.Name);
// প্রোপার্টির তথ্য বের করা
Console.WriteLine("\nProperties:");
foreach (PropertyInfo property in type.GetProperties())
{
Console.WriteLine(property.Name + " : " + property.PropertyType);
}
// মেথডের তথ্য বের করা
Console.WriteLine("\nMethods:");
foreach (MethodInfo method in type.GetMethods())
{
Console.WriteLine(method.Name + " : " + method.ReturnType);
}
}
}
Person
ক্লাসের টাইপ (Type) সংগ্রহ করা হয়েছে।Person
ক্লাসের প্রোপার্টির নাম এবং টাইপ সংগ্রহ করা হয়েছে।Person
ক্লাসের মেথডের নাম এবং রিটার্ন টাইপ সংগ্রহ করা হয়েছে।ধরা যাক, Person
ক্লাসের DisplayInfo
মেথডটি রিফ্লেকশন ব্যবহার করে ইনভোক করতে চাই।
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
Type type = typeof(Person);
// Person অবজেক্ট তৈরি
object personInstance = Activator.CreateInstance(type);
// প্রোপার্টি সেট করা
PropertyInfo nameProperty = type.GetProperty("Name");
nameProperty.SetValue(personInstance, "John Doe");
PropertyInfo ageProperty = type.GetProperty("Age");
ageProperty.SetValue(personInstance, 30);
// DisplayInfo মেথড ইনভোক করা
MethodInfo displayMethod = type.GetMethod("DisplayInfo");
displayMethod.Invoke(personInstance, null);
}
}
Person
ক্লাসের একটি অবজেক্ট তৈরি করা হয়েছে।DisplayInfo
মেথডটি ইনভোক করা হয়েছে, যা অবজেক্টের Name
এবং Age
প্রিন্ট করবে।আউটপুট:
Name: John Doe, Age: 30
Type
, MethodInfo
, PropertyInfo
, এবং FieldInfo
ব্যবহার করে ক্লাস, মেথড, প্রোপার্টি ইত্যাদির তথ্য সংগ্রহ করা হয়।রিফ্লেকশন ব্যবহারে C# প্রোগ্রামে অনেক ডায়নামিক অ্যাপ্লিকেশন তৈরি করা যায়, তবে এর কিছু সীমাবদ্ধতাও রয়েছে যা উন্নয়নকারীদের মাথায় রাখা উচিত।
জেনেরিক্স (Generics) হলো সি#-এর একটি শক্তিশালী ফিচার, যা ডেটা টাইপ নির্দিষ্ট না করে কোডের মডুলারিটি এবং পুনঃব্যবহারযোগ্যতা বাড়ায়। জেনেরিক্স ব্যবহার করে একই ক্লাস, মেথড, ডেলিগেট বা ইন্টারফেসকে একাধিক ডেটা টাইপের জন্য ব্যবহার করা যায়। এটি টাইপ-সেফটি বজায় রাখে এবং রানটাইম ত্রুটি প্রতিরোধ করে।
জেনেরিক ক্লাস ব্যবহার করে এমন একটি ক্লাস তৈরি করা যায় যা একাধিক টাইপের সাথে কাজ করতে পারে।
csharp
Copy code
public class MyGenericClass<T>
{
private T data;
public MyGenericClass(T value)
{
data = value;
}
public T GetData()
{
return data;
}
}
var intObj = new MyGenericClass<int>(10);
Console.WriteLine("Integer Value: " + intObj.GetData());
var stringObj = new MyGenericClass<string>("Hello");
Console.WriteLine("String Value: " + stringObj.GetData());
এখানে MyGenericClass<T>
ক্লাসটি int
এবং string
দুই ধরনের ডেটা টাইপের সাথে কাজ করতে সক্ষম।
জেনেরিক মেথডের মাধ্যমে একটি মেথড তৈরি করা যায় যা একাধিক টাইপের ইনপুট গ্রহণ করতে পারে।
public class MyGenericMethods
{
public void Display<T>(T data)
{
Console.WriteLine("Data: " + data);
}
}
MyGenericMethods myGeneric = new MyGenericMethods();
myGeneric.Display<int>(100);
myGeneric.Display<string>("Hello Generics");
এখানে Display
মেথডটি int
এবং string
উভয় ধরনের ইনপুট গ্রহণ করেছে।
জেনেরিক ইন্টারফেস ব্যবহার করে ইন্টারফেসের ডেটা টাইপ নির্দিষ্ট করা যায়।
public interface IRepository<T>
{
void Add(T item);
T Get(int id);
}
public class EmployeeRepository : IRepository<Employee>
{
private List<Employee> employees = new List<Employee>();
public void Add(Employee employee)
{
employees.Add(employee);
}
public Employee Get(int id)
{
return employees.FirstOrDefault(e => e.ID == id);
}
}
এখানে IRepository<T>
ইন্টারফেসে Employee
টাইপ ব্যবহার করা হয়েছে।
জেনেরিক কনস্ট্রেইন্ট ব্যবহার করে নির্দিষ্ট ধরনের ডেটা টাইপ কেবলমাত্র গ্রহণ করা যায়।
public class MyGenericClass<T> where T : class
{
public T Data { get; set; }
}
where T : class
কনস্ট্রেইন্ট ব্যবহার করে কেবলমাত্র রেফারেন্স টাইপ (ক্লাস) গ্রহণ করা হচ্ছে। অন্যান্য কনস্ট্রেইন্টগুলো:
সি# এ জেনেরিক্স ব্যবহারে বক্সিং এবং আনবক্সিং এড়ানো যায়, ফলে মেমোরি ব্যবস্থাপনা উন্নত হয় এবং পারফরম্যান্স ভালো হয়।
List<int> numbers = new List<int>();
numbers.Add(10); // এখানে বক্সিং বা আনবক্সিং এর প্রয়োজন নেই
সি# এ কিছু গুরুত্বপূর্ণ জেনেরিক ক্লাস রয়েছে যা ডেটা স্ট্রাকচার এবং কালেকশন পরিচালনায় সহায়ক। যেমন:
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
names.Add("David");
names.ForEach(name => Console.WriteLine(name));
Dictionary<int, string> studentGrades = new Dictionary<int, string>();
studentGrades[1] = "A";
studentGrades[2] = "B";
Console.WriteLine(studentGrades[1]); // Output: A
সি# এ জেনেরিক্সের ব্যবহার কোডকে আরও সংক্ষিপ্ত, টাইপ-সেফ, এবং পুনঃব্যবহারযোগ্য করে তোলে। এটি ডেটা স্ট্রাকচার এবং কালেকশন পরিচালনায় সহায়ক এবং জটিল সফটওয়্যার অ্যাপ্লিকেশন তৈরি করতে অপরিহার্য।
ডায়নামিক টাইপিং এবং dynamic কীওয়ার্ড C# এ প্রোগ্রামিংকে আরও ফ্লেক্সিবল এবং ডায়নামিক করে তোলে। ডায়নামিক টাইপিং হলো একটি প্রক্রিয়া, যার মাধ্যমে ভেরিয়েবলের টাইপ কম্পাইল টাইমে নির্ধারণ না হয়ে রানটাইমে নির্ধারিত হয়। C# এ dynamic
কীওয়ার্ড ব্যবহার করে ডায়নামিক টাইপিং করা যায়, যার ফলে কম্পাইলার সেই ভেরিয়েবলের টাইপ চেক করে না বরং তা রানটাইমে চেক করা হয়।
dynamic
কীওয়ার্ড দিয়ে ডায়নামিক টাইপের ভেরিয়েবল ডিক্লেয়ার করা হয়। এটি যেকোনো টাইপের মান ধারণ করতে পারে এবং এর মান যেকোনো সময় পরিবর্তন করা যেতে পারে। তবে, কম্পাইল টাইমে টাইপ চেক না হওয়ায় ভেরিয়েবলে টাইপ-সংক্রান্ত কোনো ত্রুটি থাকলেও তা রানটাইমে চিহ্নিত হয়।
dynamic variable = "Hello, World!";
Console.WriteLine(variable); // Output: Hello, World!
variable = 10; // String থেকে Int এ পরিবর্তন করা হয়েছে
Console.WriteLine(variable); // Output: 10
variable
ভেরিয়েবলে একটি string
মান অ্যাসাইন করা হয়েছে।int
মান অ্যাসাইন করা হয়েছে। যেহেতু এটি dynamic
টাইপের, তাই বিভিন্ন টাইপের মান সেট করা যায়।dynamic
টাইপের ভেরিয়েবল চেক করে না, বরং রানটাইমে ভেরিয়েবলের টাইপ চেক করে।dynamic
এবং object
টাইপের মধ্যে কিছু মৌলিক পার্থক্য আছে:
object obj = "Hello, World!";
Console.WriteLine(((string)obj).Length); // টাইপ কাস্ট প্রয়োজন
dynamic dyn = "Hello, World!";
Console.WriteLine(dyn.Length); // টাইপ কাস্ট প্রয়োজন নেই
ধরা যাক, আমরা একটি Excel অ্যাপ্লিকেশন রান করতে চাই। COM Interop এর মাধ্যমে dynamic ব্যবহার করে এটি করা যায়।
using System;
using Excel = Microsoft.Office.Interop.Excel;
public class Program
{
public static void Main()
{
dynamic excelApp = new Excel.Application();
excelApp.Visible = true;
dynamic workbook = excelApp.Workbooks.Add();
dynamic worksheet = workbook.Sheets[1];
worksheet.Cells[1, 1].Value = "Hello, Excel!";
}
}
ExpandoObject
এর মাধ্যমে dynamic টাইপ ব্যবহার করে নতুন প্রোপার্টি যোগ করা যায়।
using System;
using System.Dynamic;
public class Program
{
public static void Main()
{
dynamic person = new ExpandoObject();
person.Name = "John";
person.Age = 30;
Console.WriteLine("Name: " + person.Name);
Console.WriteLine("Age: " + person.Age);
}
}
person
নামে একটি dynamic অবজেক্ট তৈরি করা হয়েছে।person
অবজেক্টে Name
এবং Age
প্রোপার্টি ডায়নামিকভাবে যোগ করা হয়েছে।C# এ dynamic কীওয়ার্ড ব্যবহার করে ডায়নামিক প্রোগ্রামিং করা সহজ, তবে এটি ব্যবহারের ক্ষেত্রে সতর্ক থাকতে হয়, কারণ এটি টাইপ সেফটি কমিয়ে দেয় এবং পারফরম্যান্সেও কিছুটা প্রভাব ফেলতে পারে।
ডিপেনডেন্সি ইনজেকশন (Dependency Injection) হলো একটি ডিজাইন প্যাটার্ন, যা ক্লাসের মধ্যে নির্দিষ্ট ডিপেনডেন্সি বা নির্ভরশীলতা সরাসরি তৈরি না করে বাইরের উৎস থেকে সরবরাহ করা হয়। এর ফলে কোডের মডুলারিটি ও টেস্টেবিলিটি বৃদ্ধি পায় এবং লুজ কাপলিং নিশ্চিত হয়। ডিপেনডেন্সি ইনজেকশন সি# সহ বিভিন্ন আধুনিক প্রোগ্রামিং ভাষায় জনপ্রিয় একটি প্যাটার্ন।
ডিপেনডেন্সি ইনজেকশন তিন ধরনের হতে পারে:
কনস্ট্রাক্টর ইনজেকশনে ডিপেনডেন্সি কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হয়। এটি সবচেয়ে সাধারণ এবং প্রচলিত পদ্ধতি।
csharp
Copy code
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("Log: " + message);
}
}
public class OrderService
{
private readonly ILogger _logger;
public OrderService(ILogger logger)
{
_logger = logger;
}
public void ProcessOrder()
{
_logger.Log("Order processed successfully.");
}
}
ILogger logger = new ConsoleLogger();
OrderService orderService = new OrderService(logger);
orderService.ProcessOrder();
এখানে OrderService
ক্লাসটি ILogger
ইন্টারফেসের উপর নির্ভরশীল, কিন্তু এটি সরাসরি ConsoleLogger
তৈরি করে না, বরং বাইরের উৎস থেকে এটি ইনজেক্ট করা হয়। এতে লুজ কাপলিং এবং টেস্টেবিলিটি বৃদ্ধি পায়।
প্রোপার্টি ইনজেকশন ব্যবহারে ডিপেনডেন্সি ক্লাসের প্রোপার্টি হিসেবে সেট করা হয়।
public class OrderService
{
public ILogger Logger { get; set; }
public void ProcessOrder()
{
Logger?.Log("Order processed successfully.");
}
}
OrderService orderService = new OrderService();
orderService.Logger = new ConsoleLogger();
orderService.ProcessOrder();
এখানে ILogger
প্রোপার্টি হিসেবে ইনজেক্ট করা হয়েছে। এটি ঐচ্ছিক ডিপেনডেন্সির জন্য উপযুক্ত।
মেথড ইনজেকশনে নির্দিষ্ট মেথডের প্যারামিটার হিসেবে ডিপেনডেন্সি ইনজেক্ট করা হয়।
public class OrderService
{
public void ProcessOrder(ILogger logger)
{
logger.Log("Order processed successfully.");
}
}
OrderService orderService = new OrderService();
orderService.ProcessOrder(new ConsoleLogger());
এখানে ProcessOrder
মেথডে ILogger
প্যারামিটার হিসেবে ইনজেক্ট করা হয়েছে। এই পদ্ধতি সাধারণত অস্থায়ী বা নির্দিষ্ট মেথডের জন্য প্রয়োজনীয় ডিপেনডেন্সি ব্যবহারে কার্যকর।
ASP.NET Core-এ ডিপেনডেন্সি ইনজেকশন বিল্ট-ইন সমর্থন করে। সার্ভিসগুলো Startup
ক্লাসের ConfigureServices
মেথডে রেজিস্টার করা হয়।
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ILogger, ConsoleLogger>();
services.AddScoped<OrderService>();
}
public class OrderController : Controller
{
private readonly OrderService _orderService;
public OrderController(OrderService orderService)
{
_orderService = orderService;
}
public IActionResult Index()
{
_orderService.ProcessOrder();
return View();
}
}
এখানে OrderService
ডিপেনডেন্সি OrderController
এ ইনজেক্ট করা হয়েছে, যা Startup
ক্লাসে রেজিস্টার করা আছে।
পদ্ধতি | ব্যবহার |
---|---|
কনস্ট্রাক্টর ইনজেকশন | কনস্ট্রাক্টরের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা |
প্রোপার্টি ইনজেকশন | প্রোপার্টির মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা |
মেথড ইনজেকশন | মেথডের প্যারামিটার হিসেবে ডিপেনডেন্সি ইনজেক্ট করা |
AddScoped | ASP.NET Core এ প্রতিটি রিকোয়েস্টে নতুন ইনস্ট্যান্স প্রদান করা |
AddSingleton | অ্যাপ্লিকেশন চলাকালীন একটি মাত্র ইনস্ট্যান্স প্রদান করা |
AddTransient | প্রতিবার সার্ভিস কলের সময় নতুন ইনস্ট্যান্স প্রদান করা |
ডিপেনডেন্সি ইনজেকশন কোডকে আরও মডুলার এবং টেস্টেবল করে এবং ASP.NET Core এর মতো ফ্রেমওয়ার্কে বিল্ট-ইন সমর্থনের মাধ্যমে এটি অত্যন্ত কার্যকর।
আরও দেখুন...