Start Debugging

.NET 10 раздул ваш список NIC? Фильтрация GetAllNetworkInterfaces() без самообмана

Как фильтровать GetAllNetworkInterfaces() в .NET 10, когда виртуальные адаптеры из Hyper-V, Docker, WSL и VPN затопляют список. Включает двухступенчатый фильтр с явными компромиссами.

Если вы только что мигрировали приложение с .NET 8 на .NET 10 и внезапно NetworkInterface.GetAllNetworkInterfaces() возвращает 80 адаптеров вместо 10, вам не показалось. Это всплыло в треде 7 января 2026 года, ровно с той реальной болью, из-за которой “мелкие” изменения поведения ощущаются как ломающие: виртуальные интерфейсы Hyper-V, Docker, WSL, VPN, loopback и других системных адаптеров начинают вытеснять “настоящие” Ethernet- и Wi-Fi-устройства.

Источник: NetworkInterface.GetAllNetworkInterfaces breaking change (r/dotnet)

Неудобная правда: “физический” — это эвристика

System.Net.NetworkInformation не даёт вам единого официального булева в стиле “это физическая NIC”, которому можно было бы доверять между машинами, драйверами и функциями Windows. Безопаснее всего построить фильтр под нужды вашего продукта и сделать этот фильтр аудируемым и тестируемым.

Начните со строгих сигналов, которые обычно коррелируют с “полезным для связи”:

Затем добавьте более мягкие, специфичные для среды исключения (Docker, Hyper-V, WSL, VPN) на втором этапе.

Двухступенчатый фильтр, который явно показывает компромиссы

В треде предложили такой подход (подрезанный и слегка укреплённый ради читаемости):

using System.Net.NetworkInformation;

var candidates = NetworkInterface.GetAllNetworkInterfaces()
    .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
    .Where(nic => nic.NetworkInterfaceType is
        NetworkInterfaceType.Ethernet or
        NetworkInterfaceType.Wireless80211 or
        NetworkInterfaceType.GigabitEthernet)
    .Where(nic => !LooksVirtual(nic))
    .ToArray();

static bool LooksVirtual(NetworkInterface nic)
{
    var desc = (nic.Description ?? "").ToLowerInvariant();
    var name = (nic.Name ?? "").ToLowerInvariant();

    string[] keywords =
    {
        "virtual", "hyper-v", "vmware", "virtualbox",
        "docker", "vpn", "tap-", "wsl", "pseudo"
    };

    return keywords.Any(k => desc.Contains(k) || name.Contains(k));
}

Костыльно? Да. Но это и честно: вы признаёте, что кодируете политику.

Чтобы сделать это менее хрупким, не полагайтесь только на строки:

Отлаживайте это как продакшн-инцидент, а не как любопытный факт

Когда количество ваших адаптеров меняется между версиями .NET, относитесь к этому как к наблюдаемой разнице в поведении:

.NET 10 даёт вам сырой список. Ваше приложение всё равно должно решать, что значит “настоящий”.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад