Sunny, ref и out - это маршалинг-подсказка + контракт с компилятором. Ref и out - перенос в дни COM - подсказки для объектов при отправке по проводам / между процессами.
Контракт out
void foo( out MyClass x)
- foo () установит для
x
значение, прежде чем оно вернется.
x
не имеет значения при вводе foo (), и вы получите ошибку компилятора, если попытаетесь использовать x
перед его установкой. (использование неназначенного параметра x)
Контракт ref
void foo( ref MyClass x)
- ref позволяет изменить ссылку на вызывающего абонента.
- х должен быть назначен
- вы не можете привести что-либо к промежуточной переменной foo (ref (object) что-то)
- х не может быть собственностью
Реальность последних двух пунктов, скорее всего, помешает вам делать то, что вы пытаетесь сделать, потому что в действительности они не имеют смысла, когда вы понимаете, какие на самом деле ссылки. Если вы хотите это знать, спросите Джона Скита (он написал книгу).
Когда выполняется сортировка ref, он говорит, что в дополнение к возвращаемому значению, также возвращают значения ref.
При маршалинге говорится, что не стоит отправлять значение out при вызове метода, но не забудьте вернуть значение out в дополнение к возвращаемому значению.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ
Как отмечают другие, происходит что-то подозрительное. Похоже, что код грубой силы, который вы поддерживаете, имеет некоторые тонкие ошибки и страдает от кодирования по совпадению. Лучшее решение, вероятно, это добавить еще один слой косвенности. т.е. оболочка к классу-оболочке, которая обеспечивает детерминированную очистку, где вы можете написать грязный код один раз и только один раз вместо того, чтобы распространять его по всей базе кода.
Это сказал ..
Альтернатива 1
Ref не справится, если вы не предоставите перегрузки для каждого типа (com) объекта, с которым будете вызывать его.
// need a remove method for each type.
void Remove( ref Com1 x ) { ...; x = null; }
void Remove( ref Con2 x ) { ...; x = null; }
void Remove( ref Com3 x ) { ...; x = null; }
// a generics version using ref.
void RemoveComRef<ComT>(ref ComT t) where ComT : class
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(t);
t = null;
}
Com1 c1 = new Com1();
Com2 c2 = new Com2();
Remove( ref c1 );
RemoveComRef(ref c2); // the generics version again.
Альтернатива 2
Если вы не хотите этого делать, верните null из метода Remove () и приведите обратно к типу объекта.
class Remover
{
// .net 1.1 must cast if assigning
public static object Remove(object x)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(x);
return null;
}
// uses generics.
public static ComT RemoveCom<ComT>(ComT t) where ComT : class
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(t);
return null;
}
}
Com1 c1 = new Com1();
Com2 c2 = new Com2();
c1 = (Com1)Remover.Remove(c1); // no reliance on generics
c2 = Remover.RemoveCom(c2); // relies on generics
* Я добавил общие версии для сравнения.
Приведенный выше код приводит к тому, что при взгляде на код вы становитесь подозрительным, когда видите вызов Remove (x) без присваивания (что делает неправильный код неправильным). Вы могли бы даже Grep через кодовую базу, ища вызовы Удалить, где назначение не имеет места.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ - все вышеизложенное основано на том, что вам нужно вручную установить нулевую ссылку, что (как правило) не требуется.