Что некоторые “хорошие” пути состоят в том, чтобы использовать longjmp/setjmp для обработки ошибок C?

Свободные API кажутся такой хорошей идеей, пока кто-то не захочет насмехаться над ними.

Однако, по крайней мере, клиент графа Neo4JClient основан на интерфейсах.

Вы можете сделать что-то вроде этого (вам нужно изменить аргумент конструктора на IGraphClient вместо GraphClient.

public class BaseRepositoryTests
{
    private readonly BaseRepository<Model> subject;
    private readonly Mock<ICypherFluentQuery> mockCypher;
    private readonly Mock<ICypherFluentQuery> mockMatch;
    private readonly Mock<IGraphClient> mockGraphClient;

    public BaseRepositoryTests()
    {
        mockMatch = new Mock<ICypherFluentQuery>();

        mockCypher = new Mock<ICypherFluentQuery>();
        mockCypher
            .Setup(x => x.Match(It.IsAny<string[]>()))
            .Returns(mockMatch.Object);

        mockGraphClient = new Mock<IGraphClient>();
        mockGraphClient
            .Setup(x => x.Cypher)
            .Returns(mockCypher.Object);

        subject = new BaseRepository<Model>(mockGraphClient.Object);
    }

    [Fact]
    public async Task CanGetAll()
    {
        IEnumerable<Model> mockReturnsResult = new List<Model> { new Model() };

        var mockReturn = new Mock<ICypherFluentQuery<Model>>();

        mockMatch
            .Setup(x => x.Return(It.IsAny<Expression<Func<ICypherResultItem, Model>>>()))
            .Returns(mockReturn.Object);

        mockReturn
            .Setup(x => x.ResultsAsync)
            .Returns(Task.FromResult(mockReturnsResult));

        var result = await subject.GetAllAsync();

        Assert.Single(result);
    }

    public class Model { }
}
20
задан Jonathan Leffler 17 October 2015 в 21:07
поделиться

5 ответов

Посмотрите на этот пример / учебник:
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html

12
ответ дан 30 November 2019 в 00:09
поделиться

Я только когда-либо нашел одно использование для setjmp () / longjmp () , и это не было связано с обработкой ошибок.

На самом деле нет необходимости использовать его для этого, поскольку он всегда может быть преобразован во что-то более простое для понимания. Использование setjmp () / longjmp () очень похоже на goto в том смысле, что им легко злоупотреблять. Все, что делает ваш код менее читабельным, в целом является плохой идеей. Обратите внимание, что я не говорю, что они по своей сути плохие, просто они могут привести к плохому коду легче, чем альтернативы.

FWIW, единственное место, где они были неоценимы, был проект, который я делал в первые годы развития отрасли ( MS-DOS 6 таймфрейм).

5
ответ дан 30 November 2019 в 00:09
поделиться

В Symbian реализован механизм Leave в терминах longjmp () , и это служит хорошим обзором всего, что вам нужно сделать.

В Symbian есть глобальный «стек очистки», который вы нажимаете и выталкиваете вещи, которые хотите очистить в случае прыжка. Это ручная альтернатива автоматическому разматыванию стека, которое делает компилятор C ++ при возникновении исключения C ++.

В Symbian были «ловушки», к которым он мог бы выпрыгнуть; они могут быть вложенными.

(Symbian совсем недавно переопределил его в терминах исключений C ++, но интерфейс остается неизменным).

В целом, я думаю, что собственные исключения C ++ менее подвержены ошибкам кодирования и намного быстрее, чем переход ваш собственный эквивалент C.

(Современные компиляторы C ++ отлично справляются с «нулевыми накладными расходами» исключения, когда они не выброшены, например; longjmp () должен хранить состояние всех регистров и тому подобное, даже если переход не выполняется позднее, поэтому принципиально никогда не может быть таким же быстрым, как исключения.)

Использование C ++ как лучшего C, где вы принимаете только исключения и RAII, будет хорошим маршрутом, если вам будет заманчиво использовать longjmp () для эмуляции исключений.

5
ответ дан 30 November 2019 в 00:09
поделиться

Исключения являются гораздо лучшим общим механизмом, но в глубокие темные времена прошлого C я написал эмулятор процессора, который включал командную оболочку. Оболочка, используемая для setjmp / longjmp для обработки прерываний (т. Е. Процессор работает, и пользователь нажимает break / ctrl-c, код перехватывает SIGINT и longjmps обратно в оболочку).

0
ответ дан 30 November 2019 в 00:09
поделиться

If you are worried about resource cleanup, you have to seriously wonder whether longjmp() and setjmp() are a good idea.

If you design your resource allocation system so that you can in fact clean up accurately, then it is OK - but that design tends to be tricky, and typically incomplete if, in fact, the standard libraries that your code uses themselves allocate resources that must be released. It requires extraordinary care, and because it is not wholly reliable, it is not suitable for long-running systems that might need to survive multiple uses of the setjmp()/longjmp() calls (they'll leak, expand, and eventually cause problems).

14
ответ дан 30 November 2019 в 00:09
поделиться
Другие вопросы по тегам:

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