Paweł Łukasiewicz: programista blogger
Paweł Łukasiewicz
2026-04-01
Paweł Łukasiewicz: programista blogger
Paweł Łukasiewicz
2026-04-01
Udostępnij Udostępnij Kontakt
Wprowadzenie

Extension methods (C# 3.0, 2007) były rewolucją - pozwoliły rozszerzać typy bez modyfikowania ich kodu. Ale przez 19 lat mogłeś rozszerzać tylko metody. W 2026 roku wszystko się zmienia!

C# 14 wprowadza kompletny system extension members: extension properties, extension operators, static extension members, i nową składnię extension blocks. To największa zmiana w rozszerzalności typów od czasu LINQ!

📅 Timeline - ewolucja extension members
  • C# 3.0 (2007) - 🔥 Extension methods - LINQ revolution!
  • C# 3.0-13 (2007-2025) - Tylko methods przez 19 lat
  • C# 14 (2026) - 🔥🔥 Extension properties - wreszcie!
  • C# 14 (2026) - 🔥 Extension operators
  • C# 14 (2026) - 🔥 Static extension members
  • C# 14 (2026) - 🔥 Extension blocks - nowa składnia
Extension Methods - przypomnienie (C# 3.0)

Podstawy extension methods

// Extension methods - znane od C# 3.0 (2007)
public static class StringExtensions
{
    // Extension method - static method w static class
    // Pierwszy parametr z 'this' wskazuje rozszerzany typ
    public static string Reverse(this string str)
    {
        char[] chars = str.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }
    
    public static bool IsNullOrEmpty(this string? str)
    {
        return string.IsNullOrEmpty(str);
    }
    
    public static int WordCount(this string str)
    {
        return str.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

// Użycie - jak normalne metody!
string text = "Hello World";
string reversed = text.Reverse();        // "dlroW olleH"
int words = text.WordCount();            // 2
bool empty = text.IsNullOrEmpty();       // false

// LINQ to extension methods!
var numbers = new[] { 1, 2, 3, 4, 5 };
var even = numbers.Where(n => n % 2 == 0);  // Where to extension method!

Ograniczenia extension methods

// Do C# 13 - TYLKO methods!

public static class StringExtensions
{
    // ✅ Extension method - OK
    public static string Reverse(this string str) { /* ... */ }
    
    // ❌ Extension property - NIEMOŻLIWE przed C# 14!
    // public static int Length(this string str) { get; }
    
    // ❌ Extension operator - NIEMOŻLIWE przed C# 14!
    // public static string operator +(this string a, string b) { /* ... */ }
    
    // ❌ Extension static member - NIEMOŻLIWE przed C# 14!
    // public static string Empty(this string) { /* ... */ }
}

// Problemy:
// 1. Nie możesz dodać computed property
// 2. Nie możesz dodać operator overloading
// 3. Nie możesz dodać static members
// 4. Musisz tworzyć osobne static classes dla każdego typu
🔥 Extension Properties - wreszcie! (C# 14)

Problem bez extension properties

// Przed C# 14 - musisz użyć method zamiast property
public static class StringExtensions
{
    // Method zamiast property 😞
    public static bool IsEmpty(this string str)
    {
        return str.Length == 0;
    }
    
    public static string GetReversed(this string str)
    {
        return new string(str.Reverse().ToArray());
    }
}

// Użycie - wywołanie metody, nie property access
string text = "Hello";
bool empty = text.IsEmpty();        // Wygląda jak metoda
string rev = text.GetReversed();    // Wygląda jak metoda

// Chciałbyś:
// bool empty = text.IsEmpty;  // Jako property!
// string rev = text.Reversed;  // Jako property!

Rozwiązanie - Extension Properties!

🎉 REWOLUCJA C# 14 - Extension Properties

Możesz rozszerzać typy o properties! Wygląda jak normalna property!

// C# 14 - extension properties!
public static class StringExtensions
{
    // Extension property - get-only
    public static bool IsEmpty(this string str)
    {
        get => str.Length == 0;
    }
    
    // Extension property - computed
    public static string Reversed(this string str)
    {
        get => new string(str.Reverse().ToArray());
    }
    
    // Extension property - z logiką
    public static int WordCount(this string str)
    {
        get => str.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

// Użycie - jak normalna property! ✨
string text = "Hello World";
bool empty = text.IsEmpty;      // Property access!
string rev = text.Reversed;     // Property access!
int words = text.WordCount;     // Property access!

// Wygląda naturalnie, jak gdyby string miał te properties! 🎉
❌ C# 3-13 - method
public static class ListExtensions
{
    public static bool IsEmpty(this List list)
    {
        return list.Count == 0;
    }
    
    public static T GetLast(this List list)
    {
        return list[list.Count - 1];
    }
}

// Użycie - wywołanie metody
var list = new List { 1, 2, 3 };
bool empty = list.IsEmpty();  // ()
int last = list.GetLast();    // ()
✅ C# 14 - property
public static class ListExtensions
{
    public static bool IsEmpty(this List list)
    {
        get => list.Count == 0;
    }
    
    public static T Last(this List list)
    {
        get => list[list.Count - 1];
    }
}

// Użycie - property access! ✨
var list = new List { 1, 2, 3 };
bool empty = list.IsEmpty;  // Bez ()!
int last = list.Last;       // Bez ()!

Extension properties z get i set

// Extension property z get/set
public static class ListExtensions
{
    // Read-only extension property
    public static bool IsEmpty(this List list)
    {
        get => list.Count == 0;
    }
    
    // Extension property z get/set
    public static T FirstOrDefault(this List list)
    {
        get => list.Count > 0 ? list[0] : default(T);
        set
        {
            if (list.Count == 0)
                list.Add(value);
            else
                list[0] = value;
        }
    }
}

// Użycie
var numbers = new List { 1, 2, 3 };

// Get
int first = numbers.FirstOrDefault;  // 1

// Set
numbers.FirstOrDefault = 99;  // Zmienia list[0] na 99
Console.WriteLine(numbers[0]);  // 99

Extension properties dla value types

// Extension properties dla DateTime
public static class DateTimeExtensions
{
    public static bool IsWeekend(this DateTime date)
    {
        get => date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;
    }
    
    public static bool IsWeekday(this DateTime date)
    {
        get => !date.IsWeekend;
    }
    
    public static int DayOfYear(this DateTime date)
    {
        get => date.DayOfYear;
    }
    
    public static string MonthName(this DateTime date)
    {
        get => date.ToString("MMMM");
    }
}

// Użycie
var today = DateTime.Now;
bool weekend = today.IsWeekend;      // Property!
bool weekday = today.IsWeekday;      // Property!
string month = today.MonthName;      // "February"

// Extension properties dla int
public static class IntExtensions
{
    public static bool IsEven(this int number)
    {
        get => number % 2 == 0;
    }
    
    public static bool IsPositive(this int number)
    {
        get => number > 0;
    }
    
    public static string Ordinal(this int number)
    {
        get => number switch
        {
            1 => "1st",
            2 => "2nd",
            3 => "3rd",
            _ => $"{number}th"
        };
    }
}

int x = 5;
bool even = x.IsEven;        // false
bool positive = x.IsPositive;  // true
string ord = x.Ordinal;      // "5th"
🔥 Extension Operators (C# 14)

Problem - brak operator extensions

// Chcesz dodać operator+ dla string concatenation z obiektem
public class Person
{
    public string Name { get; set; }
}

// Przed C# 14 - musisz modyfikować class Person
// public class Person
// {
//     public static string operator +(string s, Person p) { /* ... */ }
// }
// Ale nie możesz modyfikować string!

// Extension method to workaround
public static class StringPersonExtensions
{
    public static string Concat(this string s, Person p)
    {
        return s + p.Name;
    }
}

// Użycie - brzydkie
string result = "Hello ".Concat(new Person { Name = "Jan" });
// Chciałbyś: "Hello " + person

Rozwiązanie - Extension Operators!

🎉 REWOLUCJA C# 14 - Extension Operators

Możesz dodawać operator overloading jako extensions!

// C# 14 - extension operator!
public static class StringPersonExtensions
{
    // Extension operator+ dla string i Person
    public static string operator +(this string s, Person p)
    {
        return s + p.Name;
    }
    
    // Extension operator* - repeat string
    public static string operator *(this string s, int count)
    {
        return string.Concat(Enumerable.Repeat(s, count));
    }
}

// Użycie - naturalny operator syntax! ✨
var person = new Person { Name = "Jan" };
string result = "Hello " + person;  // "Hello Jan"

string repeated = "Ha" * 3;  // "HaHaHa"

// Wygląda jak native operator! 🎉

Extension comparison operators

// Extension operators dla custom comparisons
public class Version
{
    public int Major { get; set; }
    public int Minor { get; set; }
}

public static class VersionExtensions
{
    // Extension operator>
    public static bool operator >(this Version v1, Version v2)
    {
        if (v1.Major != v2.Major)
            return v1.Major > v2.Major;
        return v1.Minor > v2.Minor;
    }
    
    // Extension operator<
    public static bool operator <(this Version v1, Version v2)
                                       {
                                       if (v1.Major !=v2.Major)
                                       return v1.Major < v2.Major;
        return v1.Minor < v2.Minor;
    }

    // Extension operator==
    public static bool operator ==(this Version v1, Version v2)
    {
        return v1.Major == v2.Major && v1.Minor == v2.Minor;
    }

    // Extension operator!=
    public static bool operator !=(this Version v1, Version v2)
    {
        return !(v1 == v2);
    }
}

// Użycie
var v1 = new Version { Major = 2, Minor = 1 };
var v2 = new Version { Major = 1, Minor = 9 };

bool greater = v1 > v2;  // true - operator extension!
bool equal = v1 == v2;   // false

Extension arithmetic operators

// Extension operators dla Vector
public class Vector2
{
    public double X { get; set; }
    public double Y { get; set; }
}

public static class Vector2Extensions
{
    // Extension operator+
    public static Vector2 operator +(this Vector2 v1, Vector2 v2)
    {
        return new Vector2 { X = v1.X + v2.X, Y = v1.Y + v2.Y };
    }
    
    // Extension operator-
    public static Vector2 operator -(this Vector2 v1, Vector2 v2)
    {
        return new Vector2 { X = v1.X - v2.X, Y = v1.Y - v2.Y };
    }
    
    // Extension operator* (scalar multiply)
    public static Vector2 operator *(this Vector2 v, double scalar)
    {
        return new Vector2 { X = v.X * scalar, Y = v.Y * scalar };
    }
    
    // Extension operator/ (scalar divide)
    public static Vector2 operator /(this Vector2 v, double scalar)
    {
        return new Vector2 { X = v.X / scalar, Y = v.Y / scalar };
    }
}

// Użycie - naturalny syntax!
var v1 = new Vector2 { X = 3, Y = 4 };
var v2 = new Vector2 { X = 1, Y = 2 };

var sum = v1 + v2;        // Vector2 { X = 4, Y = 6 }
var diff = v1 - v2;       // Vector2 { X = 2, Y = 2 }
var scaled = v1 * 2;      // Vector2 { X = 6, Y = 8 }
var divided = v1 / 2;     // Vector2 { X = 1.5, Y = 2 }
🔥 Static Extension Members (C# 14)

Problem - brak static extensions

// Chcesz dodać static factory method do typu
public class User
{
    public string Name { get; set; }
    public string Email { get; set; }
}

// Przed C# 14 - musisz użyć osobnej static class
public static class UserFactory
{
    public static User CreateGuest()
    {
        return new User { Name = "Guest", Email = "guest@example.com" };
    }
}

// Użycie - nie wygląda jak część User
var guest = UserFactory.CreateGuest();  // Osobna klasa

// Chciałbyś:
// var guest = User.CreateGuest();  // Jak gdyby było w User!

Rozwiązanie - Static Extension Members!

🎉 REWOLUCJA C# 14 - Static Extension Members

Możesz dodawać static members do typów przez extensions!

// C# 14 - static extension members!
public static class UserExtensions
{
    // Static extension method
    public static User CreateGuest(this User)
    {
        return new User { Name = "Guest", Email = "guest@example.com" };
    }
    
    // Static extension method z parametrami
    public static User Create(this User, string name, string email)
    {
        return new User { Name = name, Email = email };
    }
    
    // Static extension property
    public static User Empty(this User)
    {
        get => new User { Name = "", Email = "" };
    }
}

// Użycie - wygląda jak static members User! ✨
var guest = User.CreateGuest();  // Jak gdyby było w User!
var user = User.Create("Jan", "jan@example.com");
var empty = User.Empty;

// Natural syntax! 🎉

Static extension dla built-in types

// Static extensions dla int
public static class IntExtensions
{
    // Static factory methods
    public static int Parse(this int, string s, int defaultValue = 0)
    {
        return int.TryParse(s, out int result) ? result : defaultValue;
    }
    
    // Static constants
    public static int MaxSafeInteger(this int)
    {
        get => 2147483647;
    }
    
    public static int MinSafeInteger(this int)
    {
        get => -2147483648;
    }
}

// Użycie
int parsed = int.Parse("123", defaultValue: 0);  // Extension!
int max = int.MaxSafeInteger;  // Extension property!

// Static extensions dla DateTime
public static class DateTimeExtensions
{
    public static DateTime Today(this DateTime)
    {
        get => DateTime.Today;
    }
    
    public static DateTime Yesterday(this DateTime)
    {
        get => DateTime.Today.AddDays(-1);
    }
    
    public static DateTime Tomorrow(this DateTime)
    {
        get => DateTime.Today.AddDays(1);
    }
}

// Użycie
var today = DateTime.Today;        // Extension property!
var yesterday = DateTime.Yesterday;  // Extension property!
var tomorrow = DateTime.Tomorrow;    // Extension property!
🔥 Extension Blocks - nowa składnia (C# 14)

Problem - rozproszony kod extensions

// Przed C# 14 - osobne static classes dla każdego typu
public static class StringExtensions
{
    public static string Reverse(this string str) { /* ... */ }
    public static bool IsEmpty(this string str) { get => /* ... */ }
}

public static class ListExtensions
{
    public static bool IsEmpty(this List list) { get => /* ... */ }
    public static T Last(this List list) { get => /* ... */ }
}

public static class IntExtensions
{
    public static bool IsEven(this int n) { get => /* ... */ }
    public static bool IsPrime(this int n) { /* ... */ }
}

// Rozproszony kod - trudny w maintanance
// Trzeba pamiętać o naming conventions
// Trzeba pamiętać że class musi być static

Rozwiązanie - Extension Blocks!

🎉 REWOLUCJA C# 14 - Extension Blocks

Nowa składnia extension Type { } - elegancko grupuj extensions!

// C# 14 - extension block!
extension string
{
    // Methods
    public static string Reverse()
    {
        return new string(this.Reverse().ToArray());
    }
    
    public static int WordCount()
    {
        return this.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
    
    // Properties
    public static bool IsEmpty
    {
        get => this.Length == 0;
    }
    
    public static string Reversed
    {
        get => this.Reverse();
    }
    
    // Operators
    public static string operator *(int count)
    {
        return string.Concat(Enumerable.Repeat(this, count));
    }
}

// Użycie - identyczne jak wcześniej
string text = "Hello";
string rev = text.Reverse();     // Method
bool empty = text.IsEmpty;       // Property
string repeated = text * 3;      // Operator

// Ale kod jest elegancko zgrupowany! ✨

Extension blocks dla generics

// Extension block dla List
extension List
{
    // Generic extension property
    public static bool IsEmpty
    {
        get => this.Count == 0;
    }
    
    public static T Last
    {
        get => this[this.Count - 1];
    }
    
    public static T FirstOrDefault
    {
        get => this.Count > 0 ? this[0] : default(T);
        set
        {
            if (this.Count == 0)
                this.Add(value);
            else
                this[0] = value;
        }
    }
    
    // Generic extension method
    public static List Shuffle()
    {
        var rnd = new Random();
        return this.OrderBy(_ => rnd.Next()).ToList();
    }
    
    // Static factory
    public static List Create(params T[] items)
    {
        return new List(items);
    }
}

// Użycie
var numbers = new List { 1, 2, 3, 4, 5 };
bool empty = numbers.IsEmpty;      // Property
int last = numbers.Last;           // Property
var shuffled = numbers.Shuffle();  // Method

var created = List.Create(1, 2, 3);  // Static factory

Extension blocks dla interfaces

// Extension block dla IEnumerable
extension IEnumerable
{
    // Extension property
    public static bool Any
    {
        get => this.Any();
    }
    
    public static int Count
    {
        get => this.Count();
    }
    
    // Extension method
    public static T[] ToArray()
    {
        return this.ToArray();
    }
    
    public static List ToList()
    {
        return this.ToList();
    }
    
    // Helper methods
    public static string JoinString(string separator = ", ")
    {
        return string.Join(separator, this);
    }
}

// Użycie - na WSZYSTKICH IEnumerable!
var numbers = new[] { 1, 2, 3, 4, 5 };
bool any = numbers.Any;           // Property extension
int count = numbers.Count;        // Property extension
string joined = numbers.JoinString();  // "1, 2, 3, 4, 5"
❌ Stara składnia - rozproszony kod
public static class StringExtensions
{
    public static string Reverse(this string str) { }
    public static bool IsEmpty(this string str) { get; }
}

public static class StringOperatorExtensions
{
    public static string operator *(this string s, int c) { }
}

public static class StringFactoryExtensions
{
    public static string Empty(this string) { get; }
}

// 3 klasy dla jednego typu! 😱
✅ Extension block - zgrupowane
extension string
{
    // Methods
    public static string Reverse() { }
    
    // Properties
    public static bool IsEmpty { get; }
    
    // Operators
    public static string operator *(int c) { }
    
    // Static members
    public static string Empty { get; }
}

// Wszystko w jednym miejscu! ✨
Praktyczne zastosowania

Przykład 1: String helpers - complete toolkit

// Kompletny string extension toolkit w C# 14
extension string
{
    // Properties
    public static bool IsEmpty { get => this.Length == 0; }
    public static bool IsNullOrEmpty { get => string.IsNullOrEmpty(this); }
    public static bool IsNullOrWhiteSpace { get => string.IsNullOrWhiteSpace(this); }
    public static string Reversed { get => new string(this.Reverse().ToArray()); }
    
    // Methods
    public static string Truncate(int maxLength, string suffix = "...")
    {
        if (this.Length <= maxLength) return this;
        return this[..maxLength] + suffix;
    }
    
    public static string ToTitleCase()
    {
        return string.Join(" ", 
            this.Split(' ')
                .Select(word => char.ToUpper(word[0]) + word[1..].ToLower())
        );
    }
    
    public static bool Contains(string value, StringComparison comparison)
    {
        return this.Contains(value, comparison);
    }
    
    public static int WordCount
    {
        get => this.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
    
    // Operators
    public static string operator *(int count)
    {
        return string.Concat(Enumerable.Repeat(this, count));
    }
    
    // Static helpers
    public static string Empty { get => string.Empty; }
    public static string NewLine { get => Environment.NewLine; }
}

// Użycie
string text = "hello world from c#";
bool empty = text.IsEmpty;              // Property
string title = text.ToTitleCase();      // "Hello World From C#"
string truncated = text.Truncate(10);   // "hello worl..."
int words = text.WordCount;             // 4
string repeated = "Ha" * 3;             // "HaHaHa"

Przykład 2: Collection extensions z operators

// Collections extensions w C# 14
extension List
{
    // Properties
    public static bool IsEmpty { get => this.Count == 0; }
    public static bool IsNotEmpty { get => this.Count > 0; }
    public static T First { get => this[0]; }
    public static T Last { get => this[this.Count - 1]; }
    
    // Methods
    public static List Shuffle()
    {
        var rnd = new Random();
        return this.OrderBy(_ => rnd.Next()).ToList();
    }
    
    public static T? SecondOrDefault()
    {
        return this.Count >= 2 ? this[1] : default;
    }
    
    public static List Slice(int start, int end)
    {
        return this.Skip(start).Take(end - start).ToList();
    }
    
    // Operators - combine lists
    public static List operator +(List other)
    {
        var result = new List(this);
        result.AddRange(other);
        return result;
    }
    
    // Operator - remove elements
    public static List operator -(List other)
    {
        return this.Except(other).ToList();
    }
    
    // Static factories
    public static List Create(params T[] items)
    {
        return new List(items);
    }
    
    public static List Repeat(T item, int count)
    {
        return Enumerable.Repeat(item, count).ToList();
    }
}

// Użycie
var list1 = new List { 1, 2, 3 };
var list2 = new List { 3, 4, 5 };

bool empty = list1.IsEmpty;           // Property
int first = list1.First;              // Property
int last = list1.Last;                // Property

var combined = list1 + list2;         // Operator+ : [1, 2, 3, 3, 4, 5]
var difference = list1 - list2;       // Operator- : [1, 2]

var shuffled = list1.Shuffle();       // Method
var slice = list1.Slice(1, 3);        // [2, 3]

var created = List.Create(1, 2, 3);  // Static factory

Przykład 3: DateTime extensions

// DateTime extensions w C# 14
extension DateTime
{
    // Properties
    public static bool IsWeekend { get => this.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday; }
    public static bool IsWeekday { get => !this.IsWeekend; }
    public static bool IsToday { get => this.Date == DateTime.Today; }
    public static bool IsPast { get => this < DateTime.Now; }
    public static bool IsFuture { get => this > DateTime.Now; }
    public static string MonthName { get => this.ToString("MMMM"); }
    public static int Quarter { get => (this.Month - 1) / 3 + 1; }
    
    // Methods
    public static DateTime StartOfDay()
    {
        return this.Date;
    }
    
    public static DateTime EndOfDay()
    {
        return this.Date.AddDays(1).AddTicks(-1);
    }
    
    public static DateTime StartOfMonth()
    {
        return new DateTime(this.Year, this.Month, 1);
    }
    
    public static DateTime EndOfMonth()
    {
        return this.StartOfMonth().AddMonths(1).AddTicks(-1);
    }
    
    public static int DaysUntil(DateTime other)
    {
        return (other - this).Days;
    }
    
    // Operators
    public static TimeSpan operator -(DateTime other)
    {
        return this - other;
    }
    
    // Static helpers
    public static DateTime Now { get => DateTime.Now; }
    public static DateTime Today { get => DateTime.Today; }
    public static DateTime Yesterday { get => DateTime.Today.AddDays(-1); }
    public static DateTime Tomorrow { get => DateTime.Today.AddDays(1); }
}

// Użycie
var date = new DateTime(2026, 2, 25);

bool weekend = date.IsWeekend;        // Property
bool weekday = date.IsWeekday;        // Property
string month = date.MonthName;        // "February"
int quarter = date.Quarter;           // 1

var startDay = date.StartOfDay();     // Method
var endMonth = date.EndOfMonth();     // Method

var yesterday = DateTime.Yesterday;   // Static property
var tomorrow = DateTime.Tomorrow;     // Static property

Przykład 4: Numeric extensions z INumber<T>

using System.Numerics;

// Generic numeric extensions dla ALL numeric types!
extension T where T : INumber
{
    // Properties
    public static bool IsZero { get => this == T.Zero; }
    public static bool IsPositive { get => this > T.Zero; }
    public static bool IsNegative { get => this < T.Zero; }
    
    // Methods
    public static T Squared()
    {
        return this * this;
    }
    
    public static T Cubed()
    {
        return this * this * this;
    }
    
    public static T Abs()
    {
        return T.Abs(this);
    }
    
    public static T Clamp(T min, T max)
    {
        if (this < min) return min;
        if (this > max) return max;
        return this;
    }
    
    // Static helpers
    public static T Zero { get => T.Zero; }
    public static T One { get => T.One; }
}

// Działa dla WSZYSTKICH numeric types! ✨
int x = 5;
bool zero = x.IsZero;           // false
bool positive = x.IsPositive;   // true
int squared = x.Squared();      // 25
int cubed = x.Cubed();          // 125

double y = -3.5;
bool negative = y.IsNegative;   // true
double abs = y.Abs();           // 3.5
double clamped = y.Clamp(0, 10);  // 0
Podsumowanie

Extension Members w C# 14 - kompletna rewolucja w rozszerzalności!

  • Extension methods (C# 3.0) - przypomnienie, LINQ foundation
  • 🔥🔥 Extension properties (C# 14) - wreszcie! Get/set support
  • 🔥 Extension operators (C# 14) - +, -, *, /, ==, !=, <,>
  • 🔥 Static extension members (C# 14) - static methods i properties
  • 🔥 Extension blocks (C# 14) - extension Type { } syntax
  • Generic extensions - extension blocks z constraints
  • Interface extensions - IEnumerable<T>, INumber<T>
  • Praktyczne przykłady - string, collections, DateTime, numerics

W kolejnym wpisie skupimy się na Pattern Matching - Type/Property/Positional/List/Logical patterns!

Zadanie dla Ciebie 🎯

Stwórz kompletny extension toolkit dla List<T> używając C# 14:

extension List
{
    // Properties do dodania:
    // - IsEmpty, IsNotEmpty
    // - First, Last, SecondOrDefault
    
    // Methods do dodania:
    // - Shuffle(), Slice(start, end)
    // - AddRange(params T[] items)
    // - RemoveAll(Func predicate)
    
    // Operators do dodania:
    // - operator+ (combine lists)
    // - operator- (remove elements)
    
    // Static do dodania:
    // - Create(params T[] items)
    // - Repeat(T item, int count)
}

Wymagania:

  1. Użyj extension List<T> { } block syntax
  2. Co najmniej 5 properties
  3. Co najmniej 5 methods
  4. Co najmniej 2 operators
  5. Co najmniej 2 static members
🎯 BONUS: Complete Math Extensions Library

Stwórz kompletną bibliotekę matematyczną dla ALL numeric types używając extension blocks!

Do zaimplementowania:

  1. Extension block dla INumber<T>:
    • Properties: IsZero, IsPositive, IsNegative, IsEven (dla integer types)
    • Methods: Squared, Cubed, Power(n), Factorial (dla integer)
    • Methods: Abs, Sign, Clamp, InRange
    • Operators: % (mod dla negative numbers - proper modulo)
  2. Extension block dla IFloatingPoint<T>:
    • Methods: Round(decimals), Floor, Ceiling
    • Methods: ToRadians, ToDegrees
    • Properties: IsNaN, IsInfinity
  3. Extension block dla Vector2<T> i Vector3<T>:
    • Properties: Magnitude, Normalized
    • Methods: Dot, Cross (dla Vector3), Distance, Lerp
    • Operators: +, -, *, / (scalar)
    • Static: Zero, One, Up, Down, Left, Right
  4. Extension block dla Matrix<T>:
    • Properties: Determinant, Transpose
    • Methods: Multiply, Inverse
    • Operators: +, -, *
    • Static: Identity, Zero

Przykład użycia:

// Numeric extensions - działa dla int, double, decimal, etc
int x = 5;
bool even = x.IsEven;           // Property
int squared = x.Squared();      // Method
int cubed = x.Cubed();          // Method
int factorial = x.Factorial();  // 120

double angle = 90.0;
double radians = angle.ToRadians();  // Method
double rounded = 3.14159.Round(2);   // 3.14

// Vector extensions
var v1 = new Vector2(3, 4);
var v2 = new Vector2(1, 2);

double mag = v1.Magnitude;         // Property: 5.0
var normalized = v1.Normalized;    // Property
var sum = v1 + v2;                // Operator
var dot = v1.Dot(v2);             // Method: 11
var distance = v1.Distance(v2);   // Method

var zero = Vector2.Zero;  // Static property

// Matrix extensions
var m1 = new Matrix2x2(1, 2, 3, 4);
var m2 = new Matrix2x2(5, 6, 7, 8);

double det = m1.Determinant;      // Property: -2
var transposed = m1.Transpose;    // Property
var product = m1 * m2;            // Operator
var identity = Matrix2x2.Identity;  // Static

Ten projekt demonstruje pełną moc C# 14 extension members - properties, operators, static members, extension blocks, generic constraints! 🚀✨🔢