В чем разница между ManagementObject и ManagementBaseObject

Когда я скомпилировал следующие оба кода, он дает тот же результат (я так думаю).

//ManagementObject :
SelectQuery query = new SelectQuery("Win32_Environment");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
  Console.WriteLine("Variable : {0}, Value = {1}",envVar["Name"], envVar["VariableValue"]);

//ManagementBaseObject :
SelectQuery query = new SelectQuery("Win32_Environment");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementBaseObject envVar in searcher.Get())
  Console.WriteLine("Variable : {0}, Value = {1}",envVar["Name"], envVar["VariableValue"]);

в чем разница между выполнением кода ...?

1
nl ja de

2 ответы

В этом конкретном случае нет никакой разницы.

Метод ManagementObjectSearcher.Get() возвращает ManagementObjectCollection , который представляет собой коллекцию ManagementBaseObject . Это означает, что коллекция может содержать экземпляры типа ManagementBaseObject или любого времени, которое происходит от ManagementBaseObject .

Тем не менее, ManagementBaseObject разработан как базовый класс, а это значит, что на самом деле он не будет создан, но вместо этого будут созданы экземпляры спускаемых классов. Обратите внимание, что это просто соглашение, и оно не обеспечивается языком или каркасом.

Кроме того, поскольку единственный класс в структуре, который (непосредственно) наследует ManagementBaseObject , является ManagementObject , Get() эффективно возвращает коллекцию экземпляров ManagementObject . Обратите внимание, что это только текущая ситуация, и ничто не мешает созданию дополнительных ManagementBaseObject наследников.

Таким образом, при всех предостережениях, связанных с метионом, это означает, что если вы используете только свойства, определенные в базовом классе (а не чрезмерно), вы можете итерации в любом случае, и код будет вести себя точно так же. в вашем коде используется только индексатор , который действительно определен и не переопределяется в классе ManagementBaseObject .

Если вам нужен пример кода, который завершится с ошибкой для одного цикла и будет работать в другом, вы можете попробовать любое из свойств, определенных в ManagementObject , например, Путь :

foreach (ManagementObject envVar in searcher.Get())
  Console.WriteLine("Path : {0}, Value = {1}",envVar.Path.Path); //works

foreach (ManagementBaseObject envVar in searcher.Get())
  Console.WriteLine("Path : {0}, Value = {1}",envVar.Path.Path); //compile error
2
добавлено
Обратите внимание, однако, что тот факт, что первая версия с использованием ManagementObject работает только из-за того, что в настоящее время нет других типов, происходящих из ManagementBaseObject . Это ничего не гарантирует договор метода Get() .
добавлено автор Dirk Vollmar, источник
Добавлена ​​немного более сильная формулировка, чтобы подчеркнуть этот факт. Хотя я сомневаюсь, что дизайн этих классов будет когда-либо изменяться (и они были вокруг в течение длительного времени ), используя этот код, полагаясь на недоказанное и неподдерживаемое предположение.
добавлено автор SWeko, источник

Вы должны использовать ManagementBaseObject здесь. Метод Get() возвращает (не общий) ManagementObjectCollection , который содержит ManagementBaseObject -пределенные типы, включая ManagementObject и ManagementClass .

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

Если вам нужно только рассмотреть объекты типа ManagementObject , вы можете рассмотреть следующую версию:

var query = new SelectQuery("Win32_Environment");
var searcher = new ManagementObjectSearcher(query);
foreach (var envVar in searcher.Get().OfType())
{
    Console.WriteLine("Variable: {0}, Value = {1}", 
        envVar["Name"], envVar["VariableValue"]);
}
1
добавлено