Showing posts with label CSharp. Show all posts
Showing posts with label CSharp. Show all posts

Wednesday, October 30, 2024

Delegate and Event, Additional FAQs

Question1

Delegate is a type in C#. Delegate and event are closely related. Is event is a type in C#?

Yes, in C#, an event is technically a member, not a type itself. It acts as a special form of delegate, providing a way to encapsulate a delegate and control how it’s accessed from outside the containing class.

Attribute in C#, Additional FAQs

Question1

Can Attribute based class in C# can be a static class?
No, an attribute class in C# cannot be a static class. In C#, attribute classes must inherit from System.Attribute, and they are instantiated when applied to program elements like classes, methods, properties, etc. Since static classes cannot be instantiated, they cannot be used as attribute classes.

Sunday, October 27, 2024

How can you call a method of base class in derived class in C#?

In C#, you cannot directly call a private method (or any member) from a base class in a derived class. Private members are not accessible outside the class in which they are defined, even in derived classes. However, if you want to call a method that's marked as protected or internal (or any other access modifier that allows visibility to derived classes), you can call it from the derived class.

Difference between IEnumerable and IEnumerator in C#

IEnumerable and IEnumerator are both interfaces in C# that are used to work with collections of data, particularly when you want to iterate (loop) through the elements of a collection. They play different roles in the process of iterating through a collection. Here are the key differences between them:

Difference between TryParse and Parse in C#

TryParse and Parse are methods used in C# to convert a string representation of a value into its corresponding data type, such as an integer, floating-point number, or date.

Custom Exception in C#

In C#, a custom exception is a user-defined exception that extends the built-in Exception class or any of its derived classes. Creating custom exceptions allows you to handle specific error cases in your application in a more meaningful and organized way.

C# Custom Attribute Example

In C#, custom attributes (also known as custom metadata or annotations) allow you to attach additional information or metadata to various program entities such as classes, methods, properties, and more. These attributes are then accessible at runtime using reflection, which allows you to inspect and manipulate the behavior of your code based on this metadata. Custom attributes are commonly used in scenarios like serialization, validation, and code documentation.

Here's an example of creating a custom attribute in C#:
using System;

// Define a custom attribute called "AuthorAttribute" that can be applied to classes and methods.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }

    public AuthorAttribute(string name)
    {
        Name = name;
    }
}

// Apply the custom attribute to a class and a method.
[Author("John Doe")]
class MyClass
{
    [Author("Alice Smith")]
    public void MyMethod()
    {
        Console.WriteLine("Hello, world!");
    }
}

class Program
{
    static void Main()
    {
        // Use reflection to access and display the custom attribute values.
        Type myClassType = typeof(MyClass);
        object[] classAttributes = myClassType.GetCustomAttributes(typeof(AuthorAttribute), false);

        if (classAttributes.Length > 0)
        {
            AuthorAttribute classAuthorAttribute = (AuthorAttribute)classAttributes[0];
            Console.WriteLine($"Author of MyClass: {classAuthorAttribute.Name}");
        }

        var myMethod = typeof(MyClass).GetMethod("MyMethod");
        object[] methodAttributes = myMethod.GetCustomAttributes(typeof(AuthorAttribute), false);

        if (methodAttributes.Length > 0)
        {
            AuthorAttribute methodAuthorAttribute = (AuthorAttribute)methodAttributes[0];
            Console.WriteLine($"Author of MyMethod: {methodAuthorAttribute.Name}");
        }
    }
}

In this example:
  1. We define a custom attribute called AuthorAttribute that takes a string parameter in its constructor.
  2. We apply this custom attribute to both a class (MyClass) and a method (MyMethod) using square brackets.
  3. In the Main method, we use reflection to access the custom attribute values for the MyClass and MyMethod. We retrieve the attribute objects and extract the Name property to display the author's name.

When you run this code, it will output:
Author of MyClass: John Doe
Author of MyMethod: Alice Smith
This demonstrates how custom attributes can be used to attach additional information to program entities and retrieve that information at runtime using reflection.

Saturday, October 26, 2024

C# Delegates and Events in depth

In C#, delegates and events are related and crucial concepts used for implementing the observer design pattern, enabling a way to provide notifications when certain actions or events occur in a program.

C# Task class, Asynchronous and Parallel Tasks

In C#, tasks are used to represent asynchronous operations. They are part of the Task Parallel Library (TPL) and provide a way to perform work asynchronously on a separate thread. Creating a task in C# involves using the Task class or related methods. Here are the common ways to create a task:

C# Type class and Reflextion

What is use of Type class in C#?

In C#, the Type class is a fundamental class that is a part of the .NET Framework. It represents type declarations and provides various methods and properties to obtain information about types at runtime. The Type class is a crucial part of reflection, which allows you to inspect and manipulate types, methods, properties, and other members of a program dynamically.

C# Enum In Depth

In C#, the Enum class is used to work with enumeration types, which are user-defined value types that consist of a set of named constants. Enumerations provide a way to define a collection of related named constants, which makes the code more readable and maintainable. 

C# Verbatim String Literal

In C#, a verbatim string literal is a way to specify a string without escape sequences, meaning that backslashes are treated literally rather than as escape characters. This is useful when you want to include special characters or a sequence of characters that would otherwise be interpreted as escape sequences.

To create a verbatim string literal, you prefix the string with the "@" symbol. Here's an example:
string path = @"C:\s\name\Documents";
In this example, the backslashes (\) are treated as literal characters and are not interpreted as escape sequences. This is especially helpful for file paths, regular expressions, or any other scenario where you want to include backslashes or other special characters without needing to escape them.

For comparison, the same string without using a verbatim string literal would be written like this:
string path = "C:\\s\\name\\Documents";
Using a verbatim string literal can make your code more readable and easier to work with when dealing with strings that contain many escape characters or backslashes.

Different ways to create an instance of class in C#

In C#, there are several ways to create an instance of a class, depending on the specific requirements and design patterns being used. Here are some common ways to create instances of a class:

1. Using the new Keyword:
The most common way to create an instance of a class is using the new keyword followed by the class name, followed by parentheses (if the class has a parameterless constructor).
MyClass myObject = new MyClass(); // Creating an instance using a parameterless constructor
2. Using Constructors with Parameters:
If the class has constructors with parameters, you can use these constructors to initialize the instance.
MyClass myObject = new MyClass("parameter1", 42); // Creating an instance using a constructor with parameters
3. Using Object Initializer:
This approach allows you to set the properties of the object after it's created using an initializer syntax.

MyClass myObject = new MyClass{
Property1 = "value1",      
Property2 = 42   
};
4. Using Factory Methods:
You can define static or instance methods within the class or a separate factory class to create and return instances of the class.
   
public class MyClass
{
public static MyClass CreateInstance() 
  {
  return new MyClass();
  }
}
MyClass myObject = MyClass.CreateInstance();
5. Using Object Cloning:
If your class implements ICloneable interface or provides a custom cloning mechanism, you can create a new instance by cloning an existing object.
MyClass myObject = originalObject.Clone();
6. Using Activator.CreateInstance:
The Activator class provides a generic method to create instances of a type, even when the type is not known at compile time.
MyClass myObject = Activator.CreateInstance();
7. Using Reflection:
You can use reflection to create an instance of a class dynamically, especially when the class type is determined at runtime.
Type classType = Type.GetType("Namespace.MyClass");  
MyClass myObject = (MyClass)Activator.CreateInstance(classType);
It's important to choose the appropriate approach based on the requirements of your application and the design principles you want to follow.

Records in C# Explained

In C#, a record is a feature introduced in C# 9.0 that allows you to define lightweight, immutable data structures in a concise and expressive manner. Records provide a convenient way to define types that are primarily used to store and represent data.

Here are the key aspects and features of records in C#:

1. Immutable by Default:
Records are immutable by default, meaning their values cannot be modified after creation. This is essential for creating reliable and predictable data structures.

2. Data-Centric:
Records are designed to represent data, making them an excellent choice for modeling objects that primarily hold data without behavior.

3. Concise Syntax:
C# records offer a concise syntax for defining properties and initializing their values. You can define a record using the record keyword, followed by the record's name and its properties.
   public record Person(string FirstName, string LastName);
4. Property Definitions:
Properties in a record are defined directly within the record declaration. The properties are implicitly read-only, meaning you cannot assign new values to them once the record is created.

5. Value Equality:
Records automatically implement value equality based on their property values. This means two record instances with the same property values are considered equal.

6. Deconstructor:
Records provide a deconstructor, which allows you to easily destructure a record into its constituent properties.

7. Inheritance and Overriding:
Records can inherit from other classes and interfaces, and you can override methods, including ToString(), GetHashCode(), and Equals().

Here's a simple example of using a record:
public record Person(string FirstName, string LastName);

class Program
{
    static void Main()
    {
        Person person1 = new Person("John", "Doe");
        Person person2 = new Person("John", "Doe");

        Console.WriteLine(person1.Equals(person2));  // Outputs: True

        // Deconstruction
        var (firstName, lastName) = person1;
        Console.WriteLine($"First Name: {firstName}, Last Name: {lastName}");
    }
}
In this example, we define a record Person with two properties (FirstName and LastName). We create two instances of the Person record and demonstrate value equality and deconstruction features.


Custom Constructor in Records

In C#, records are a special kind of type introduced in C# 9.0 that provides a succinct way to declare a type and is often used to model immutable data. Records automatically provide a default constructor, which initializes the properties of the record.

However, records in C# do not allow you to define a custom constructor explicitly. The default constructor is provided by the language and automatically initializes the properties based on the values provided during object creation.

Here's an example of a record in C#:
public record Person(string FirstName, string LastName);
In this example, a Person record is defined with two properties: FirstName and LastName. The default constructor for this record is automatically provided by the compiler.

If you need custom initialization logic for your record, you can still use methods or factory methods to achieve the desired behavior:
public record Person(string FirstName, string LastName)
{
    public Person(string fullName)
    {
        var parts = fullName.Split(' ');
        FirstName = parts.Length > 0 ? parts[0] : string.Empty;
        LastName = parts.Length > 1 ? parts[1] : string.Empty;
    }
}

In this modified example, we have added a custom constructor Person(string fullName) that takes a full name and initializes the FirstName and LastName properties accordingly.

Keep in mind that records are primarily designed for immutability and straightforward data representation, so complex initialization logic is generally better suited for methods or factory methods.
C# Event Definition

Can event be defined in record in C#?

In C#, events cannot be defined directly within a record type. Records are designed to be lightweight data structures that represent immutable values, and they are primarily used for data storage and retrieval. Events, on the other hand, are mechanisms used to provide notifications or callback functionality when something happens in a class or object.

If you need to define events in your C# code, you typically do so within a class rather than a record. Here's an example of how you would define an event within a class:
public class MyClass
{
    public event EventHandler MyEvent;

    public void DoSomething()
    {
        // Trigger the event when something happens
        MyEvent?.Invoke(this, EventArgs.Empty);
    }
}
In this example, MyClass has an event called MyEvent, and you can subscribe to this event and handle its occurrences in other parts of your code.

Records are more suitable for scenarios where you want to define simple data structures with value semantics and automatic implementations of equality, immutability, and other features. Events are typically associated with classes that represent behavior or functionality.

If you need a combination of events and data storage, you can use a class to encapsulate both your data and event-handling logic.

What are different ways to call a method in C#?

In C#, methods can be called in various ways depending on the context and the type of method. Here are different ways to call a method in C#:

1. Direct Method Call:
This is the most common way to call a method. You simply specify the method name followed by parentheses and any required arguments.
    methodName(argument1, argument2);

2. Calling Static Methods:
For static methods, you can call the method directly using the class name.
    ClassName.MethodName(argument1, argument2);
3. Calling Instance Methods:
For instance methods, you need to create an instance of the class and then call the method on that instance.
    ClassName instance = new ClassName();

instance.MethodName(argument1, argument2);
4. Method Chaining:
If a method returns an object of the same class, you can chain method calls together.
    instance.Method1().Method2().Method3();
5. Using Delegates:
Delegates allow you to store and call a reference to a method. You can invoke the delegate to call the method.
    delegateType delegateName = methodName;

delegateName(argument1, argument2);
6. Using Lambda Expressions:
You can create and call methods using lambda expressions, especially for delegates or functional interfaces.
    delegateType delegateName = (arg1, arg2) => { /* method implementation */ };

delegateName(argument1, argument2);
7. Using the Invoke Method:
For delegates, you can use the Invoke method to call the referenced method.
    delegateName.Invoke(argument1, argument2);
8. Using Event Handlers:
Event handlers are methods that are called when a specific event occurs. They are usually subscribed to events in the application.
    eventName += methodName; // Subscribe the method to the event
9. Using Named Arguments:
You can specify arguments by their parameter names, allowing you to provide them in a different order or omit some optional parameters.
    methodName(parameter2: value2, parameter1: value1);
These are some of the common ways to call methods in C#. The choice of method calling approach depends on the specific requirements and design of your application.

Partial class in C#

A partial class in C# allows you to split the definition of a class, struct, interface, or method across multiple files. This can be useful when working on large projects or when using auto-generated code, as it allows for organizing code in a way that separates auto-generated and manually written parts of the class. The partial keyword is used to specify that a class has been divided into parts.

Key Features of Partial Classes

  1. Organizational Clarity: Keeps code cleaner by separating different functionalities or generated code from manually written code.
  2. Team Collaboration: Multiple team members can work on the same class in different files without merging conflicts.
  3. Auto-generated Code: Useful in cases where tools like Visual Studio generate code for you, as in Windows Forms or Entity Framework.

How to Use Partial Classes

To define a partial class, declare it using the partial keyword in each file where the class definition is split. Each file must have the same class name and be in the same namespace.

Example of Partial Class

Suppose you have a class Person split into two files, Person1.cs and Person2.cs:

File: Person1.cs

public partial class Person
{

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string GetFullName()
    {
        return $"{FirstName} {LastName}";
    }
}
File: Person2.c

public partial class Person
{
    public int Age { get; set; }
    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {GetFullName()}, Age: {Age}");
    }
}

Both parts together make up the complete Person class, with FirstName, LastName, Age, and methods GetFullName and DisplayInfo.

Points to Remember

  • All parts must use the partial keyword.
  • All parts must have the same accessibility level (e.g., public, internal).
  • If partial classes contain conflicting members, a compilation error will occur.
  • The compiler combines all parts into a single class during compilation.

Use Cases

  • Generated Code: Typically used when tools or frameworks generate part of the class.
  • Large Classes: Split functionality for better organization, especially in large classes.

Partial classes are mainly used to improve code readability and maintainability, especially in projects where auto-generated code is prevalent or when dealing with large classes.

Partial Method Declaration, Implementation and Usage in C#

Partial methods in C# are a feature that allows a method to be defined in one part of a partial class and implemented in another part. Partial classes and methods are often used in code generation scenarios, where some parts of the code are generated automatically and other parts are customized by the developer.

Here are the rules for creating and using partial methods in C#:

1. Partial Methods Declaration:
   Partial methods are declared using the partial keyword in a partial class or struct. The declaration of a partial method contains only the method signature, without an implementation.

partial void MyPartialMethod(int x);

2. Partial Method Implementation:
   The partial method can be implemented in another part of the partial class or struct. The implementation of a partial method is optional, and it's not an error if the partial method is never implemented.

partial void MyPartialMethod(int x)
{
 // Implementation code here
}

3. Usage of Partial Methods:
   Partial methods can be called like any other method within the partial class. If the partial method is not implemented, any calls to it are removed by the compiler at build time, minimizing overhead.

public void SomeMethod()
{
 // Call the partial method
 MyPartialMethod(42);
}

4. Visibility and Modifiers:
   Partial methods can have any visibility modifier (public, private, protected, internal, etc.). They can also have modifiers like static, virtual, abstract, sealed, and override as applicable.

partial void MyPartialMethod(int x);

5. Return Type and Parameters:
   Partial methods can have any return type, including void. They can also have parameters, including optional parameters.

partial void MyPartialMethod(int x, string message = "Default message");

6. Partial Method Signature Constraints:
   The signature (name, return type, and parameters) of a partial method must be the same in both the declaration and the implementation.

partial void MyPartialMethod(int x);
partial void MyPartialMethod(int x) // Valid, matching signature
{
 // Implementation code here
}

7. One Declaration, One Implementation:
   A partial method can have at most one declaration and at most one implementation. If there are multiple declarations or implementations, it will result in a compilation error.

// Error: Multiple partial method declarations with the same name and signature
partial void MyPartialMethod(int x);
partial void MyPartialMethod(int x);

// Error: Multiple partial method implementations with the same name and signature
partial void MyPartialMethod(int x)
{
 // Implementation 1
}

partial void MyPartialMethod(int x)
{
 // Implementation 2
}

Partial methods are commonly used in scenarios where generated code needs to call into user-defined code without requiring the user to implement the method if it's not needed.

Extension method and use it in C#

Objectives:

  • What is Extension Method
  • How to create Extension methods 
  • How to use Extension Method

Extension methods in C# allow you to add new methods to existing types without modifying the original type or creating a new derived type. Here's how you can create and use extension methods in C#:

1. Create a static class for extension methods: First, create a static class to contain the extension methods. The class should be static, and the methods should also be static. The class should be in the same namespace as the types you want to extend.
   using System;

   public static class StringExtensions
   {
       public static string Reverse(this string str)
       {
           char[] charArray = str.ToCharArray();
           Array.Reverse(charArray);
           return new string(charArray);
       }
   }
   
In this example, we're creating an extension method called Reverse for the string type.

2. Define the extension method: The extension method is a static method defined in the static class. It takes the type to be extended as the first parameter, prefixed with the this keyword.

3. Using the extension method: You can then use the extension method on instances of the extended type.
   using System;

   class Program
   {
       static void Main(string[] args)
       {
           string originalString = "hello";
           string reversedString = originalString.Reverse();
           Console.WriteLine("Original: " + originalString);
           Console.WriteLine("Reversed: " + reversedString);
       }
   }
   
In this example, we're calling the Reverse extension method on a string instance.

4. Output: The Reverse extension method modifies the behavior of the string type without modifying the original string class.
Original: hello Reversed: olleh

Remember to include the namespace where the extension method class is defined (if it's in a different namespace) or import the namespace to use the extension methods.

Is Nested Interface allowed in C#

Nested Interfaces in C# means to define an interface inside another interface in C#. In C#, you cannot define an interface inside another interface directly. C# does not support nested interfaces like it supports nested classes. Interface definitions in C# are typically declared at the namespace level and cannot be nested within other interfaces.

However, you can have an interface that inherits from another interface. This is a form of extending an interface to include additional members while maintaining the existing members from the parent interface.
public interface IBaseInterface
{
    void SomeMethod();
}

public interface IDerivedInterface : IBaseInterface
{
    void AnotherMethod();
}
In this example, IDerivedInterface extends IBaseInterface and includes its members (SomeMethod) as well as additional members (AnotherMethod).

If you need to group related interfaces, you can place them within the same namespace or create a common base interface that is implemented by multiple interfaces to achieve the desired behavior.

Nested classes with example in C#

In C#, a nested class is a class defined within another class. This allows you to logically group related classes and keep them in a single unit. Nested classes have access to the members of the enclosing class, including private members. They can also be static or non-static.

Here's an example of nested classes in C#:

using System;

public class OuterClass
{
    private int outerData;

    public OuterClass(int data)
    {
        outerData = data;
    }

    public void DisplayOuterData()
    {
        Console.WriteLine("Outer data: " + outerData);
    }

    public class NestedClass
    {
        private int nestedData;

        public NestedClass(int data)
        {
            nestedData = data;
        }

        public void DisplayNestedData()
        {
            Console.WriteLine("Nested data: " + nestedData);
        }

        public void AccessOuterData(OuterClass outer)
        {
            Console.WriteLine("Accessing outer data from nested class: " + outer.outerData);
        }
    }
}

public class Program
{
    public static void Main()
    {
        // Creating an instance of the outer class
        OuterClass outer = new OuterClass(10);

        // Creating an instance of the nested class
        OuterClass.NestedClass nested = new OuterClass.NestedClass(20);

        // Accessing and displaying data from the outer and nested classes
        outer.DisplayOuterData();
        nested.DisplayNestedData();

        // Accessing outer data from the nested class
        nested.AccessOuterData(outer);
    }
}
In this example:
  • OuterClass is the outer class that contains the nested class NestedClass.
  • NestedClass is a nested class within OuterClass.
  • NestedClass has access to the private members of OuterClass, such as outerData.
  • The Main method demonstrates creating instances of both the outer and nested classes and accessing their members.

Hot Topics