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

File-scoped features to nowoczesne podejście do organizacji kodu! W 2015 roku każdy plik miał namespace z klamrami i długą listę using statements. W 2026 roku masz file-scoped namespaces, global usings, implicit usings, i file-local types - mniej boilerplate, czystszy kod!

📅 Timeline - ewolucja file-scoped features
  • C# 1.0-9.0 (do 2020) - Namespaces z klamrami, using w każdym pliku
  • C# 10 (2021) - 🔥 File-scoped namespaces + Global usings!
  • .NET 6+ (2021) - Implicit usings - automatyczne!
  • C# 11 (2022) - 🔥 File-local types!
Problem - boilerplate wszędzie
// Przed C# 10 - namespace z klamrami
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCompany.MyProduct.Services  // ← Klamra
{
    public class UserService  // ← Dodatkowa indentacja
    {
        public User GetUser(int id)  // ← Jeszcze więcej indentacji
        {
            return new User();
        }
    }
}  // ← Zamykająca klamra

// Problemy:
// - Dodatkowy poziom indentacji
// - Te same usingi w KAŻDYM pliku
// - Bezużyteczna zamykająca klamra
🔥 File-scoped Namespaces (C# 10)
🎉 C# 10 - File-scoped Namespace

namespace MyApp; bez klamer - jeden poziom mniej indentacji! ✨

// C# 10+ - file-scoped namespace
using System;

namespace MyCompany.MyProduct.Services;  // ← Średnik!

public class UserService  // ← Bez dodatkowej indentacji!
{
    public User GetUser(int id)
    {
        return new User();
    }
}

// Zalety:
// ✅ Jeden poziom mniej indentacji
// ✅ Brak zbędnej klamry
// ✅ Czystszy kod
❌ Przed C# 10
namespace MyApp
{
    public class User
    {
        public void Method()
        {
            // 3 poziomy!
        }
    }
}
✅ C# 10+
namespace MyApp;

public class User
{
    public void Method()
    {
        // 2 poziomy! ✨
    }
}
🔥 Global Usings (C# 10)
🎉 C# 10 - Global Usings

global using System; - raz dla CAŁEGO projektu!

// File: GlobalUsings.cs
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;

// Te usingi są dostępne w KAŻDYM pliku!

// File: UserService.cs
namespace MyApp.Services;  // ← Brak using statements!

public class UserService
{
    public List<User> GetUsers()  // List z global using!
    {
        return _users.Where(u => u.IsActive).ToList();  // Linq z global using!
    }
}

Organizacja global usings

// GlobalUsings.cs
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;
global using MyApp.Core.Entities;  // Twoje namespaces
global using Microsoft.Extensions.Logging;  // Third-party

// Teraz NIE musisz dodawać tych usings w żadnym pliku! ✨
Implicit Usings (.NET 6+)
🎉 .NET 6+ - Implicit Usings

SDK automatycznie dodaje global usings! Włączone domyślnie!

// .csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>  <!-- Domyślnie włączone -->
  </PropertyGroup>
</Project>

// SDK automatycznie dodaje:
// - System
// - System.Collections.Generic
// - System.IO
// - System.Linq
// - System.Threading
// - System.Threading.Tasks
// + więcej dla ASP.NET Core

// Efekt: Większość plików NIE POTRZEBUJE żadnych usings! ✨

Minimal API bez usings

// Program.cs - ZERO using statements!
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.MapGet("/users", async () =>
{
    await Task.Delay(100);
    return new List<User> { new User { Name = "Jan" } };
});

app.Run();

// Wszystko z implicit usings! ✨
🔥 File-local Types (C# 11)
🎉 C# 11 - File-local Types

file class - typ widoczny TYLKO w tym pliku!

// File: UserService.cs
namespace MyApp.Services;

// file class - widoczne TYLKO w tym pliku!
file class UserValidator
{
    public bool Validate(User user) => !string.IsNullOrEmpty(user.Name);
}

file record UserDto(string Name, int Age);

public class UserService
{
    public void CreateUser(User user)
    {
        var validator = new UserValidator();  // ✅ OK
        var dto = new UserDto(user.Name, user.Age);  // ✅ OK
    }
}

// File: OrderService.cs
namespace MyApp.Services;

public class OrderService
{
    // UserValidator NIE jest widoczny tutaj!
    // var v = new UserValidator();  // ❌ BŁĄD!
}

Use cases

// Helper classes używane tylko w jednym pliku
file class ReportFormatter { }
file class ReportValidator { }

// DTOs używane tylko w jednym serwisie
file record CreateUserRequest(string Name);
file record UserResponse(int Id, string Name);

// Enums używane tylko w jednej klasie
file enum ProcessingStage { Validation, Payment, Completed }
Modifier Zasięg
file class Tylko ten plik
private class (nested) Tylko outer class
internal class Cały assembly
public class Wszędzie
Organizacja kodu w 2026

Nowoczesny plik w 2026

// UserService.cs
namespace MyApp.Services;  // File-scoped

file class UserValidator { }  // File-local helper

public class UserService
{
    private readonly ILogger<UserService> _logger;  // Z global using
    
    public async Task<User> CreateUserAsync(User user)  // Task z implicit
    {
        var validator = new UserValidator();
        await _repository.SaveAsync(user);
        return user;
    }
}

// Porównaj z 2015:
// - Brak 5 linii using statements
// - Brak namespace { }
// - Jeden poziom mniej indentacji
// - Czystszy kod! ✨

Struktura projektu

// Struktura w 2026:
📁 MyApp
  📄 GlobalUsings.cs  ← Global usings
  📁 Services
    📄 UserService.cs  ← File-scoped + file-local
    📄 OrderService.cs
  📁 Controllers
    📄 UsersController.cs

// GlobalUsings.cs:
global using System;
global using System.Linq;
global using MyApp.Entities;

// Każdy plik:
namespace MyApp.Services;
file class Helper { }
public class Service { }
💡 Refactoring 2015 → 2026
// ❌ 2015 (30 linii)
using System;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp.Services
{
    public class UserService
    {
        public async Task<User> Get()
        {
            await Task.Delay(100);
            return new User();
        }
    }
}

// ✅ 2026 (15 linii - POŁOWA!)
namespace MyApp.Services;

public class UserService
{
    public async Task<User> Get()
    {
        await Task.Delay(100);
        return new User();
    }
}

Best practices

// ✅ DO:
namespace MyApp.Services;  // File-scoped
global using System;  // GlobalUsings.cs
file class Helper { }  // File-local

// ❌ DON'T:
namespace MyApp.Services { }  // Stare
using System;  // W każdym pliku
internal class Helper { }  // Użyj file
Podsumowanie

  • 🔥 File-scoped namespaces - namespace MyApp; bez klamer
  • 🔥 Global usings - global using dla całego projektu
  • Implicit usings - automatyczne od SDK
  • 🔥 File-local types - file class tylko w pliku
  • 50% mniej boilerplate - czystszy kod w 2026!

Kolejny wpis: własne operatory!