Лучший способ возвратиться рано из функции, возвращая ссылку

Типичный метод следующие. Вы сказали, что хотите сделать это в C#, таким образом, здесь идет...

  1. , Если Вы не знаете, какому процессу заблокировали файл, необходимо будет исследовать список дескриптора каждого процесса и запросить каждый дескриптор, чтобы определить, определяет ли это заблокированный файл. Выполнение в этом C#, вероятно, потребует, чтобы P/Invoke или посреднический C++ / CLI назвали встроенные API, в которых Вы будете нуждаться.
  2. , Как только Вы выяснили, какому процессу (процессам) заблокировали файл, необходимо будет безопасно ввести маленький собственный DLL в процесс (можно также ввести управляемый DLL, но это более грязно, поскольку тогда необходимо запустить или присоединить ко времени выполнения.NET).
  3. , Что DLL начальной загрузки тогда закрывает использование дескриптора CloseHandle, и т.д.

По существу: способ разблокировать "заблокированный" файл состоит в том, чтобы ввести файл DLL в незаконное адресное пространство процесса и закрыть его самостоятельно. Можно сделать этот использующий собственный или управляемый код. Неважно, что, Вы собираетесь нуждаться в небольшом количестве собственного кода или по крайней мере P/Invoke в то же.

Полезные ссылки:

Удачи!

8
задан R. Martinho Fernandes 15 November 2011 в 15:30
поделиться

13 ответов

Это не синтаксическая проблема, а проблема дизайна. Вы должны указать, что ReturnOurObject () должен возвращать, когда SomeCondition истинно. Это в основном зависит от того, для чего будет использоваться функция. И этого вы нам не сказали.

В зависимости от проблем дизайна я вижу несколько возможных синтаксических выходов из этого:

  • вернуть ссылку на какой-то другой объект; где-то у вас должен быть какой-то эрзац-объект
  • , где-то есть специальный объект «без объекта для возврата», на который вы возвращаете ссылку; клиенты могут это проверить; если они не проверяют, то получают разумное поведение по умолчанию
  • возвращают указатель, а не ссылку; клиентам придется всегда проверять возвращаемое значение функции
  • , вызывающей исключение; если SomeCondition является чем-то исключительным, с которым клиенты не могут справиться, это было бы уместно утверждать
  • ; если SomeCondition должно всегда выполняться, оно должно быть подтверждено
24
ответ дан 5 December 2019 в 04:29
поделиться

По способу настройки функции вы должны вернуть SomeObject или выбросить исключение. Если вы хотите сделать что-то еще, вам нужно изменить функцию. Других вариантов нет.

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

Есть возможность вернуть какой-то нулевой объект. Для этого полезны указатели, поскольку существует очевидное нулевое значение, которое проверяет ложность, но вы можете передать флаг обратно в качестве параметра out или вернуть специальный объект, предназначенный как null. Затем вам нужно будет проверять возвращаемое значение при каждом вызове, чтобы это было значимым, и это вряд ли будет меньше хлопот, чем assert или throw .

Если бы я делал это, это зависело бы от SomeCondition . Если он имеет побочные эффекты или его нетрудно вычислить, проверьте и выбросьте исключение, если оно ложно. Если сложно вычислить, используйте assert , чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.

s вряд ли будет меньше хлопот, чем assert или throw .

Если бы я делал это, это зависело бы от SomeCondition . Если у него есть побочные эффекты или его нетрудно вычислить, протестируйте и выбросьте исключение, если оно ложно. Если это сложно вычислить, используйте assert , чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.

s вряд ли будет меньше хлопот, чем assert или throw .

Если бы я делал это, это зависело бы от SomeCondition . Если у него есть побочные эффекты или его нетрудно вычислить, протестируйте и выбросьте исключение, если оно ложно. Если это сложно вычислить, используйте assert , чтобы вам не приходилось делать это в производственной среде, и забудьте об этом, кроме того.

0
ответ дан 5 December 2019 в 04:29
поделиться

Ровно три варианта ...

1. Вызвать исключение
2. Вернуть фиктивный объект ошибки
3. Используйте указатель и верните NULL

1
ответ дан 5 December 2019 в 04:29
поделиться

Я считаю, что ответ зависит от являетесь ли вы программистом, который считает исключения плохими и никогда не хочет их использовать, или нет. Если вы их используете, И это действительно исключительное условие, тогда должно быть создано исключение. Да, пользователям нужно с этим бороться, но скрыть ошибку, чтобы сделать вид, что ничего не произошло, просто не вариант. Но если вы никогда не используете исключения, просто верните указатель или логическое значение и добавьте неконстантную ссылку на SomeObject в свою функцию. Оба решения просты, но кто сказал, что чрезмерное усложнение делает код лучше?

0
ответ дан 5 December 2019 в 04:29
поделиться

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"))

1
ответ дан 5 December 2019 в 04:29
поделиться

Вызвать исключение

3
ответ дан 5 December 2019 в 04:29
поделиться

Я рассмотрю возможность возврата по ссылке, только если я уверен, что функция никогда не терпит неудачу (вероятно, это как возврат константной ссылки на внутреннюю переменную-член). Если внутри функции есть несколько проверок, я рассмотрю один из следующих вариантов:

  • Если копирование объекта не выполняется дорого, верните копию
  • Если копирование стоит дорого, верните константный указатель. Вернуть NULL в случае сбой.
1
ответ дан 5 December 2019 в 04:29
поделиться

Я бы вернулся логическое значение и передать ссылку на объект в качестве параметра функции:

bool getObject(SomeObject& object)
{
    if( condition )
         return false;

    object = ourObject;
    return true;
}

В этом случае теперь ваш объект был заполнен, только если функция вернула значение true.

5
ответ дан 5 December 2019 в 04:29
поделиться

Каков срок жизни 'ourObject' и где он создается?

Если вам нужно вернуться раньше, не касаясь / не обновляя наш объект, и он существует в тот момент, когда вы возвращаетесь, я не вижу проблем с возвратом ссылки на него.

Если вы пытаетесь сообщить, что произошла ошибка, вам, вероятно, придется сгенерировать исключение вместо того, чтобы возвращаться раньше, потому что в контракте, с которым ваша функция согласилась, говорится, что она вернет ссылку на 'SomeObject'.

Если вы возвращаете ссылку на временный объект, вам лучше исправить , что проблема ...

5
ответ дан 5 December 2019 в 04:29
поделиться

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.

6
ответ дан 5 December 2019 в 04:29
поделиться

В этом случае я бы использовал указатель вместо ссылки. Фактически этот критерий (необязательное или обязательное возвращаемое значение) - это то, как я в первую очередь выбираю между указателями и ссылками.

13
ответ дан 5 December 2019 в 04:29
поделиться

Э ... просто выбросить исключение ...

3
ответ дан 5 December 2019 в 04:29
поделиться

Если вы не хотите изменять тип возвращаемого значения на указатель, вы можете использовать шаблон нулевого объекта

5
ответ дан 5 December 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: