AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77706671
Accepted
José Ramírez
José Ramírez
Asked: 2023-12-23 13:01:01 +0800 CST2023-12-23 13:01:01 +0800 CST 2023-12-23 13:01:01 +0800 CST

Por que a exceção não é lançada a menos que o enumerável retornado seja enumerado e como alterar esse comportamento? [duplicado]

  • 772
Essa pergunta já tem resposta aqui :
O método com retorno de rendimento não está lançando exceção (1 resposta)
Fechado há 21 horas .

Ok, preciso de algum mestre .Net para me dizer por que a exceção no código a seguir só é lançada quando o valor de retorno é enumerado.

       public IEnumerable<string> BuildFor(Environment environment)
        {
            if (environment == Environment.None)
            {
                throw new Exception($"Impossible to build for environment '{environment}'.");
            }
            string clientId = ClientIds.Api[environment];
            foreach (string scope in scopes)
            {
                yield return $"api://{clientId}/{scope}";
            }
        }

Ok, correção: preciso de confirmação do que está acontecendo. A evidência está me dizendo que toda a chamada do método está sendo adiada, e isso é, provavelmente, uma otimização do compilador.

A pergunta seguinte: Como posso dizer ao compilador para parar de fazer isso?

c#
  • 2 2 respostas
  • 62 Views

2 respostas

  • Voted
  1. StefanFFM
    2023-12-23T13:36:56+08:002023-12-23T13:36:56+08:00

    Se você não quiser uma avaliação preguiçosa, basta escrever o método da maneira "tradicional", ou seja

    public List<string> BuildFor(Environment environment)
    {
     List<string> l = new List<string>();
    
     if (environment == Environment.None)
     {
         throw new Exception($"Impossible to build for environment '{environment}'.");
     }
     string clientId = ClientIds.Api[environment];
     foreach (string scope in scopes)
     {
        l.Add($"api://{clientId}/{scope}");
     }
    
     return l;
    }
    

    Ou você pode garantir que a avaliação ocorra no local assim:

    List<string> l = BuildFor(Environment.Env1).ToList();
    

    O compilador não tem nada a ver com isso.

    • 1
  2. Best Answer
    jmcilhinney
    2023-12-23T14:35:17+08:002023-12-23T14:35:17+08:00

    Uma opção seria tornar o iterador real um método privado chamado de dentro do método que lança a exceção. O código a seguir é muito parecido com o seu e não lançará uma exceção até entrar no segundo foreachloop do Mainmétodo:

    public static void Main()
    {
        var items = GetItems(new object());
    
        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
    
        items = GetItems(null);
    
        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
    }
    
    public static IEnumerable<string> GetItems(object obj)
    {
        var items = new[] { "First", "Second", "Third" };
    
        if (obj == null)
        {
            throw new ArgumentNullException(nameof(obj), "Argument cannot be null.");
        }
    
        foreach ( var item in items )
        {
            yield return item;
        }
    }
    

    Esta variação funciona da mesma maneira no que diz respeito à iteração, mas será lançada na segunda GetItemschamada sem esperar pela enumeração:

    public static void Main()
    {
        var items = GetItems(new object());
    
        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
    
        items = GetItems(null);
    
        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
    }
    
    public static IEnumerable<string> GetItems(object obj)
    {
        if (obj == null)
        {
            throw new ArgumentNullException(nameof(obj), "Argument cannot be null.");
        }
    
        return GetItemCore(obj);
    }
    
    private static IEnumerable<string> GetItemsCore(object obj)
    {
        var items = new[] { "First", "Second", "Third" };
    
        foreach (var item in items)
        {
            yield return item;
        }
    }
    

    Conforme sugerido nos comentários, se a sua versão do C# suportar, você poderá usar um método local em vez de um método de membro privado. Basicamente, é apenas mover o método privado para dentro do método público e remover o private static. Isso fornece a mesma funcionalidade, mas evita que esse método extra seja acessado em qualquer outro lugar, de modo que o método público ainda seja independente, como era originalmente.

    public static IEnumerable<string> GetItems(object obj)
    {
        if (obj == null)
        {
            throw new ArgumentNullException(nameof(obj), "Argument cannot be null.");
        }
    
        return GetItemsCore(obj);
    
        IEnumerable<string> GetItemsCore(object obj)
        {
            var items = new[] { "First", "Second", "Third" };
    
            foreach (var item in items)
            {
                yield return item;
            }
        }
    }
    
    • 1

relate perguntas

  • Polly DecorrelatedJitterBackoffV2 - como calcular o tempo máximo necessário para concluir todas as novas tentativas?

  • Wpf. Role o DataGrid dentro do ScrollViewer

  • A pontuação que ganhei na página do jogo com .NET MAUI MVVM não é visível em outras páginas. Como posso manter os dados de pontuação no dispositivo local

  • Use a hierarquia TreeView com HierarchicalDataTemplate de dentro de um DataTemplate

  • Como posso melhorar essa interface de validação no .NET?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve