yield permits to return a part of a result in a executing loop.

Please look at the following code that does not uses yield:

foreach cFile as string in GetFiles( "c:\" )
  WriteLine( cFile )
next

return
function GetFiles( cFolder as string ) as List<string>
local aFiles as string[]
local oFiles as List<string>

WriteLine( "start creating list" )	
oFiles := List<string>{}
aFiles := Directory.GetFiles( cFolder )
foreach cFile as string in aFiles
  oFiles:Add( cFile )
next
WriteLine( "end creating list" )	
	
return oFiles

As you would expect, this code shows the follwing output:

start creating list
end creating list
c:\bootmgr
c:\BOOTNXT
c:\bootTel.dat
c:\hiberfil.sys
c:\lang.txt
c:\pagefile.sys
c:\swapfile.sys

If you change the code to use yield, you need to change the type of your function - and your function cannot more have any return statement:

foreach cFile as string in GetFiles( "c:\" )
  WriteLine( cFile )
next

function GetFiles( cFolder as string ) as IEnumerable<string>
local aFiles as string[]
local oFiles as List<string>

WriteLine( "start creating list" )	
oFiles := List<string>{}
aFiles := Directory.GetFiles( cFolder )
foreach cFile as string in aFiles
  yield return cFile
next
WriteLine( "end creating list" )	

This code produces the following output (please note that the output is created by the calling function before the called function is finished!):

start creating list
c:\bootmgr
c:\BOOTNXT
c:\bootTel.dat
c:\hiberfil.sys
c:\lang.txt
c:\pagefile.sys
c:\swapfile.sys
end creating list

To explain a bit more: the yield returns the member of the list, and the calling code can work immediatly with instead of waiting for the called function to be complete. This is particularly useful if you have longer processes and need to refresh the user interface.