CSharp - Other

Expression in LINQ

Take the reference of System.Linq.Expressions namespace and use an Expression<TDelegate> class to define an Expression. Expression<TDelegate> requires delegate type Func or Action.


For example, you can assign lambda expression to the isTeenAger variable of Func type delegate, as shown below:


Define Func delegate for an expression in C#

public class Student 
{
  public int StudentID { get; set; }
  public string StudentName { get; set; }
  public int Age { get; set; }
}

Func<Student, bool> isTeenAger = s => s.Age > 12 && s.Age < 20;


And now, you can convert the above Func type delegate into an Expression by wrapping Func delegate with Expression, as below:


Define Expression in C#

Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20;


In the same way, you can also wrap an Action<t> type delegate with Expression if you don't return a value from the delegate.


Define Expression in C#

Expression<Action<Student>> printStudentName = s => Console.WriteLine(s.StudentName);


You can invoke the delegate wrapped by an Expression the same way as a delegate, but first you need to compile it using the Compile() method. Compile() returns delegateof Func or Action type so that you can invoke it like a delegate.


Invoke Expression in C#

Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20;

//compile Expression using Compile method to invoke it as Delegate
Func<Student, bool> isTeenAger = isTeenAgerExpr.Compile();
       
//Invoke
bool result = isTeenAger(new Student(){ StudentID = 1, StudentName = "Steve", Age = 20});

Output: false

Filter Even Numbers from an Array

Filtering out even numbers from an array is concise and efficient with LINQ.

int[] nums = { 1, 2, 3, 4, 5, 6 };
var evens = nums.Where(n => n % 2 == 0);
Console.WriteLine(string.Join(", ", evens));


Explanation: The Where method filters the array based on the condition n % 2 == 0, leaving only the even numbers, which are then printed.

Filtering the object of a type with OfType

Filtering Numeric Data


Sample Input

var mixedData = new object[] { 1, "Hello", 3.14, 42, "World", 7 };
var integers = mixedData.OfType<int>();


Expected Output

[1, 42, 7]


Extracting Strings from a List


Sample Input

var mixedData = new object[] { "Apple", 10, "Banana", 3.14, "Cherry", 42 };
var strings = mixedData.OfType<string>();


Expected Output

["Apple", "Banana", "Cherry"]


Type-Specific Operations in a UI


Sample Input

var uiElements = new object[] { new TextBox(), new Button(), new Label(), new Button() };
var buttons = uiElements.OfType<Button>();


Expected Output

[Button, Button]


Handling Polymorphic Objects


Sample Input

var vehicles = new Vehicle[] { new Car(), new Truck(), new Car(), new Bike() };
var cars = vehicles.OfType<Car>();


Expected Output

[Car, Car]


Processing Specific Exception Types


Sample Input

var exceptions = new Exception[] { new Exception(), new ArgumentException(), new NullReferenceException(), new ArgumentException() };
var argumentExceptions = exceptions.OfType<ArgumentException>();


Expected Output

[ArgumentException, ArgumentException]


Extracting Numeric Data for Calculations


Sample Input

var mixedData = new object[] { 1, 3.14, 2.71, "Hello", 42, 6.28 };
var doubles = mixedData.OfType<double>();


Expected Output

[3.14, 2.71, 6.28]


Filtering Media Content by Type


Sample Input

var mediaLibrary = new object[] { new Audio(), new Video(), new Video(), new Image() };
var videos = mediaLibrary.OfType<Video>();


Expected Output

[Video, Video]


Processing Specific Events in Logs


Sample Input

var logs = new object[] { new InfoLog(), new ErrorLog(), new DebugLog(), new ErrorLog() };
var errorLogs = logs.OfType<ErrorLog>();


Expected Output

[ErrorLog, ErrorLog]


Handling API Responses


Sample Input

var apiResponses = new object[] { new SuccessResponse(), new ErrorResponse(), new ErrorResponse(), new WarningResponse() };
var errorResponses = apiResponses.OfType<ErrorResponse>();


Expected Output

[ErrorResponse, ErrorResponse]


Analyzing Mixed Sensor Data


Sample Input

var sensorReadings = new object[] { new PressureSensorData(), new TemperatureSensorData(), new TemperatureSensorData(), new HumiditySensorData() };
var temperatureSensorData = sensorReadings.OfType<TemperatureSensorData>();


Expected Output

[TemperatureSensorData, TemperatureSensorData]


Flattening a Multi-Dimensional Array

int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
int[] flattened = matrix.Cast<int>().ToArray();
// Result: flattened = { 1, 2, 3, 4, 5, 6 }

Format a Number as Currency

Formatting numbers as currency can be achieved in a single line using ToString.

double amount = 1234.56;
Console.WriteLine(amount.ToString("C"));


Explanation: Using the "C" format specifier, this snippet converts the numeric value into a currency format based on the current culture settings.

Frozen collections

Frozen collections in .NET are special types of collections. Collections like lists, dictionaries, arrays, etc. The frozen collections can't be changed when the data has been set. We call this "immutable". This means you can look at the data inside, but you can't change the data after it's frozen.


They are really fast because your application knows the data won't change. And because of that it can prevent accidental modifications, making your application do things you don't want it to be doing.


FrozenSet<Product> frozenProducts = ProductList.Products.ToFrozenSet();

frozenProducts.Single(x => x.Title == "Meatballs").Stock = 23;

foreach (Product product in products.Where(x => x.Stock > 10))
    Console.WriteLine($"{product.Title} ({product.Stock})");

Garbage Collection Performance Monitor for .NET

public class GCPerformanceMonitor
{
    private readonly ILogger<GCPerformanceMonitor> _logger;
    private readonly Timer _monitoringTimer;
    private readonly Dictionary<string, double> _metrics = new();
    
    public GCPerformanceMonitor(ILogger<GCPerformanceMonitor> logger)
    {
        _logger = logger;
        _monitoringTimer = new Timer(CollectMetrics, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
    }
    
    private void CollectMetrics(object state)
    {
        var gcInfo = GC.GetTotalMemory(false);
        var gen0 = GC.CollectionCount(0);
        var gen1 = GC.CollectionCount(1);
        var gen2 = GC.CollectionCount(2);
        
        var previousGen0 = _metrics.GetValueOrDefault("gen0_collections", 0);
        var previousGen1 = _metrics.GetValueOrDefault("gen1_collections", 0);
        var previousGen2 = _metrics.GetValueOrDefault("gen2_collections", 0);
        
        var gen0Rate = gen0 - previousGen0;
        var gen1Rate = gen1 - previousGen1;
        var gen2Rate = gen2 - previousGen2;
        
        _metrics["gen0_collections"] = gen0;
        _metrics["gen1_collections"] = gen1;
        _metrics["gen2_collections"] = gen2;
        _metrics["total_memory"] = gcInfo;
        _metrics["gen0_rate"] = gen0Rate;
        _metrics["gen1_rate"] = gen1Rate;
        _metrics["gen2_rate"] = gen2Rate;
        
        // Alert on excessive Gen1/Gen2 collections
        if (gen1Rate > 10 || gen2Rate > 2)
        {
            _logger.LogWarning("High GC activity detected. Gen1: {Gen1Rate}/min, Gen2: {Gen2Rate}/min, Memory: {Memory:N0} bytes", 
                gen1Rate, gen2Rate, gcInfo);
        }
        
        // Log metrics for external monitoring systems
        _logger.LogInformation("GC Metrics: Gen0={Gen0Rate} Gen1={Gen1Rate} Gen2={Gen2Rate} Memory={Memory:N0}", 
            gen0Rate, gen1Rate, gen2Rate, gcInfo);
    }
    
    public void Dispose()
    {
        _monitoringTimer?.Dispose();
    }
}

Generate Tooltip via ASP.NET MVC Model Attribute

Model Attribute

[Display(Name = "Text Box Label", Description = "Text Box Tooltip Description")]


View

var description = ModelMetadata.FromStringExpression(Model.Name, ViewData).Description;

<a href="javascript:void(0)" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@description">
    <i class="fa-solid fa-circle-info"></i>
</a>


JavaScript

$(document).ready(function () {
    $('[data-bs-toggle="tooltip"]').tooltip();
})

Generate Unique ID

Guid.NewGuid().ToString("N");

Get Enum Description

public string GetEnumDescription(Enum value)
{
    FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    
    DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

    return attributes != null && attributes.Length > 0 ? attributes[0].Description : value.ToString();
}

GetEnumDescription(enumVal);

Get model's field attribute in custom editor template

ID

@ViewData.TemplateInfo.GetFullHtmlFieldId("")


Name

@ViewData.TemplateInfo.GetFullHtmlFieldName("")

GlobalUsings namespace in ASP.NET Core

Controllers & Services


The GlobalUsings.cs file is used to define global using directives. These directives allow you to import namespaces globally, meaning all files in your project automatically have access to them without needing individual using statements.

Creating GlobalUsings.cs. Place this file inside the Infrastructure folder.

global using System;
global using System.Collections.Generic;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.EntityFrameworkCore;


Razor Views


Creating _ViewImports.cshtml. Place this file inside the /Views folder.

@using Microsoft.AspNetCore.Mvc
@using Microsoft.AspNetCore.Mvc.RazorPages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers