Перечисление LINQ локальных dirves с использованием DriveInfo - PullRequest
3 голосов
/ 18 мая 2011

Я знаю, что есть много способов выполнить то, что я пытаюсь сделать здесь, но я хотел попробовать это с LINQ, и вижу некоторые странные (для меня) результаты. Надеюсь, у кого-то есть мудрость, чтобы предложить мне.

Цель - найти диск на локальном компьютере, на котором мы выполняем, с максимально доступным свободным пространством, отформатированным в файловой системе NTFS, за исключением тома% SystemDrive%, если это возможно. Еще одна оговорка: диски, которым назначена буква тома, но которые еще не отформатированы, должны быть исключены из пула кандидатов. Это крайний случай, но один клиент уже столкнулся с ним.

Итак, я пытаюсь:

string systemDrive = Environment.GetEnvironmentVariable("SystemDrive") + "\\";

List<DriveInfo> localDrives = DriveInfo.GetDrives().ToList();

var bestAPIDataDrives = from localDrive in localDrives
            orderby localDrive.AvailableFreeSpace descending
            where   localDrive.DriveType == DriveType.Fixed &&
                    localDrive.DriveFormat == "NTFS" &&
                    localDrive.RootDirectory.FullName != systemDrive &&
                    localDrive.IsReady
            select  localDrive.RootDirectory.FullName;

string path = String.Empty;

if (bestAPIDataDrives.Count() == 0)
{
    // there is only a system drive available, use it anyway.
    path = systemDrive;
}
else
{
    path = bestAPIDataDrives.ElementAt(0).ToString();
}

Когда я получаю ссылку на bestAPIDataDrives.Count (), я получаю IOException со свойством Message, установленным на «Устройство не готово».

Я не понимаю, почему это происходит, потому что у меня есть тест localDrive.IsReady в запросе LINQ, или, по крайней мере, я так думаю.

1 Ответ

4 голосов
/ 18 мая 2011

это LINQ-to-Objects, поэтому он будет выполнять операции в указанном порядке;в частности, он попытается выполнить сортировку до того, как отфильтрует, и почти все фильтры будут выполнены перед проверкой ключа IsReady.Я бы просто переупорядочил их:

var bestAPIDataDrives = from localDrive in localDrives
            where   localDrive.IsReady &&
                    localDrive.DriveType == DriveType.Fixed &&
                    localDrive.DriveFormat == "NTFS" &&
                    localDrive.RootDirectory.FullName != systemDrive     
            orderby localDrive.AvailableFreeSpace descending                   
            select  localDrive.RootDirectory.FullName;

Выполнение сортировки после фильтров - хорошая идея, так как вы уменьшаете стоимость сортировки (которая всегда суперлинейна)

Как Криспримечания, тогда вы просто хотите закончить с:

string path = bestAPIDataDrives.FirstOrDefault() ?? systemDrive;
...