Veja o código na figura que segue:
Como pode ver, temos dois breakpoints. Além disso, estamos compilando em Release.
Quando depuramos esse código, o breakpoint na primeira função é respeitado. Na segunda função, não.
EDIÇÃO: Esse comportamento pode variar dependendo do ambiente operacional e da versão do .NET que você está utilizando.
O que está acontecendo?
Deixe sua resposta nos comentários. Voltaremos com a resposta nos próximos dias.
Essa é muito facil no for a inicialização é feita somente 1x
Quando compilando em modo Release o compilador faz otimizações no código e pelo menos aqui no meu VS, na segunda função o breakpoint foi respeitado apenas 1 vez, já que na otimização o compilador leva o “var” do for para fora da instrução.
var i;
breakpoint vem pra cá => i=0;
for (; i < s.Length; i++)
{
Console.WriteLine(s[i]);
}
Assim só o breakpoint só foi respeitado uma unica vez, isso se o "Enable Just My Code" estiver desabilitado, senão nem isso ocorre.
Aqui respeitou ambos os breakpoints, acredito que o que tu está tentando ressaltar é que no segundo, irá parar somente uma vez, isso? Se colocarmos o breakpoint no “i++” ao invés da inicialização, irá parar todas as vezes, assim como no foreach.
A causa disso é o otimizador do modo release que modificou as instruções do método.
Apesar de visualmente na IDE o código ser exatamente igual entre os modos release e debug, a IL (Intermediate Language) gerada tem algumas diferenças relacionadas a otimização de código.
Para ver isso eu reproduzi esse mesmo código e abri o IL Viewer do VS e comparei um modo com o outro.
No modo debug, o método ‘GetAllChars_’ contém em sua IL todas a variáveis (.init locals) separados, que são as variáveis ‘[0] init32 i’ para o contador do laço for e ‘[1] bool V_1’ para dizer se o valor de ‘i’ e menor que a length do texto passado como argumento, se não for, saímos do laço. Em seguida temos todas as instruções separadas: carregar variáveis, obter o char da posição da variável ‘i’ no texto, imprimir no console, incrementar variável ‘i’, etc.. tudo separadinho.
Já no modo release isso não é verdade, apesar do código se comportar da mesma maneira, internamente algumas coisas foram mudadas, como a omissão da variável ‘V_1’ no inicio do método, de modo que em vez de guardar numa variável booleana se o laço for foi concluído, a verificação é feita diretamente, de maneira “inline”, tirando instruções desnecessárias e compactando o código. Porém isso torna o debug praticamente impossível, pois as instruções não estão mais lá originalmente, ou seja, é uma maneira diferente de chegar ao mesmo resultado.
No meu caso, nem o foreach funcionou o breakpoint, pois ele também foi otimizado. Fiz um console app em .NET Core.
Esqueci de dizer que estou utilizando .NET core 2.1 aqui. Verifique se é o mesmo que ocorre para você.
Reproduzindo com
VS2017 v15.9.3.
ConsoleApp. Código idêntico.
TargetFramework – netcoreapp2.1 (csproj)
Sdk Version : 2.1.507 (global.json)
Os breakpoints nos exatos lugares da imagem pararam apenas 1 vez em Debug.
Já em Release, após o F5, o breakpoint destacado no “foreach” ficou destado no “var c” e parou N vezes.
Nada mudou no outro breakpoint.