Типичный метод следующие. Вы сказали, что хотите сделать это в C#, таким образом, здесь идет...
По существу: способ разблокировать "заблокированный" файл состоит в том, чтобы ввести файл DLL в незаконное адресное пространство процесса и закрыть его самостоятельно. Можно сделать этот использующий собственный или управляемый код. Неважно, что, Вы собираетесь нуждаться в небольшом количестве собственного кода или по крайней мере P/Invoke в то же.
Полезные ссылки:
Удачи!
Это не синтаксическая проблема, а проблема дизайна. Вы должны указать, что ReturnOurObject ()
должен возвращать, когда SomeCondition
истинно. Это в основном зависит от того, для чего будет использоваться функция. И этого вы нам не сказали.
В зависимости от проблем дизайна я вижу несколько возможных синтаксических выходов из этого:
SomeCondition
является чем-то исключительным, с которым клиенты не могут справиться, это было бы уместно утверждать SomeCondition
должно всегда выполняться, оно должно быть подтверждено По способу настройки функции вы должны вернуть SomeObject
или выбросить исключение. Если вы хотите сделать что-то еще, вам нужно изменить функцию. Других вариантов нет.
Если SomeCondition
никогда не будет ложным, то вы можете удалить тест в коде и вставить вместо него assert
или оставить тест и выбросить исключение. (Я не хочу рекомендовать просто игнорировать эту возможность, поскольку «никогда не ложь» почти всегда означает «никогда не ложь, если только что-то плохое не произошло и не было обнаружено», и если это стоит проверить при любых условиях, это стоит обнаружить.)
Есть возможность вернуть какой-то нулевой объект. Для этого полезны указатели, поскольку существует очевидное нулевое значение, которое проверяет ложность, но вы можете передать флаг обратно в качестве параметра out или вернуть специальный объект, предназначенный как null. Затем вам нужно будет проверять возвращаемое значение при каждом вызове, чтобы это было значимым, и это вряд ли будет меньше хлопот, чем assert
или throw
.
Если бы я делал это, это зависело бы от SomeCondition
. Если он имеет побочные эффекты или его нетрудно вычислить, проверьте и выбросьте исключение, если оно ложно. Если сложно вычислить, используйте assert
, чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.
assert
или throw
.
Если бы я делал это, это зависело бы от SomeCondition
. Если у него есть побочные эффекты или его нетрудно вычислить, протестируйте и выбросьте исключение, если оно ложно. Если это сложно вычислить, используйте assert
, чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.
assert
или throw
.
Если бы я делал это, это зависело бы от SomeCondition
. Если у него есть побочные эффекты или его нетрудно вычислить, протестируйте и выбросьте исключение, если оно ложно. Если это сложно вычислить, используйте assert
, чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.
1. Вызвать исключение
2. Вернуть фиктивный объект ошибки
3. Используйте указатель и верните NULL
Я считаю, что ответ зависит от являетесь ли вы программистом, который считает исключения плохими и никогда не хочет их использовать, или нет. Если вы их используете, И это действительно исключительное условие, тогда должно быть создано исключение. Да, пользователям нужно с этим бороться, но скрыть ошибку, чтобы сделать вид, что ничего не произошло, просто не вариант. Но если вы никогда не используете исключения, просто верните указатель или логическое значение и добавьте неконстантную ссылку на SomeObject в свою функцию. Оба решения просты, но кто сказал, что чрезмерное усложнение делает код лучше?
If you don't want to throw an exception, you could try something like:
const SomeObject& GetSomeObject(const SomeObject& default_if_not_found = SomeObject())
{
// ...
if (!found)
return default_if_not_found;
return ourObject;
}
This means you don't have to have some kind of static variable lying around somewhere to return, and you can still call it with no parameters. I guess you'd assume the default-constructed SomeObject() state is the empty state so you can test SomeObject to see if it is in the empty state. It's also sometimes useful to use this to override the default return value, eg. GetSomeObject(SomeObject("I'm empty"))
Я рассмотрю возможность возврата по ссылке, только если я уверен, что функция никогда не терпит неудачу (вероятно, это как возврат константной ссылки на внутреннюю переменную-член). Если внутри функции есть несколько проверок, я рассмотрю один из следующих вариантов:
Я бы вернулся логическое значение и передать ссылку на объект в качестве параметра функции:
bool getObject(SomeObject& object)
{
if( condition )
return false;
object = ourObject;
return true;
}
В этом случае теперь ваш объект был заполнен, только если функция вернула значение true.
Каков срок жизни 'ourObject' и где он создается?
Если вам нужно вернуться раньше, не касаясь / не обновляя наш объект, и он существует в тот момент, когда вы возвращаетесь, я не вижу проблем с возвратом ссылки на него.
Если вы пытаетесь сообщить, что произошла ошибка, вам, вероятно, придется сгенерировать исключение вместо того, чтобы возвращаться раньше, потому что в контракте, с которым ваша функция согласилась, говорится, что она вернет ссылку на 'SomeObject'.
Если вы возвращаете ссылку на временный объект, вам лучше исправить , что проблема ...
I'd probably do this:
const SomeObject& SomeScope::ReturnOurObject()
{
if( ! SomeCondition )
{
throw SomeException();
}
return ourObject;
}
const SomeObject *SomeScope::ReturnOurObjectIfPermitted()
{
return SomeCondition ? &ourObject : 0;
}
And perhaps also:
bool SomeScope::CheckMode();
return SomeCondition;
}
Callers then have some options:
// 1 - "I know that I'm in the right mode"
myScope.ReturnOurObject().DoSomething();
// 2 - "I don't know whether I'm in the right mode, but I can cope either way"
if (SomeObject *myObject = myScope.ReturnOurObjectIfPermitted()) {
myObject->DoSomething();
} else {
DoSomethingElse();
}
// 2 - alternate version:
if (myScope.CheckMode()) {
SomeObject &myObject = myScope.ReturnOurObject();
myObject.DoSomething();
} else {
DoSomethingElse();
}
// 3 - "I don't know whether I'm in the right mode. If I'm not then
// I can't deal with it now, but some higher-level code can"
try {
// ... several calls deep ...
myScope.ReturnOurObject().DoSomething();
// ... several returns back ...
} catch (SomeException &e) {
DoSomethingElse();
}
You design a function's interface differently according to what the preconditions are, i.e. whose responsibility it is to ensure it can do its job.
If it's the caller's responsibility, then they need the ability to ensure that. You might want to check anyway, just to be on the safe side. Throwing an exception when the so-called "preconditions" aren't met makes them more like advice than conditions, and it can work quite well provided you don't mind the runtime overhead of checks everywhere. I'm usually fairly unforgiving with preconditions, so actually I might replace the conditional exception with an assert, and document that the function must not be called in the wrong mode. It depends how much control the caller has over the mode - obviously if it changes arbitrarily (e.g., if "SomeCondition" is "there is not a byte available on the UART") then you need a very different interface from if it only ever changes when the client code calls some function to change it.
If it's not the caller's responsibility to get the mode right, then your interface shouldn't write cheques that your implementation can't cash. In this case if it's "expected" that there will be no object to return, then the return should not be by reference. Unless either (a) you can rustle up a special "sorry, it didn't work" object to return, that the caller can check for, or (b) you're comfortable throwing exceptions in "expected" situations. IMO (b) is rare in C++. (a) usually isn't any better than returning a null pointer, but occasionally it is. For instance returning an empty collection to mean "there's nothing you're allowed to see here" might result in some very clean calling code, if DoSomethingElse()
would have been "do nothing". So as well as the desired responsibilities, the interface depends on the expected use cases.
В этом случае я бы использовал указатель вместо ссылки. Фактически этот критерий (необязательное или обязательное возвращаемое значение) - это то, как я в первую очередь выбираю между указателями и ссылками.
Если вы не хотите изменять тип возвращаемого значения на указатель, вы можете использовать шаблон нулевого объекта