Technically? Yes, absolutely. Goto programs are turing complete and as such you can represent everything as them. In the end, machine code is pretty much similar to a goto program as loops and stuff are all done using conditional jumps. Of course in .NET you won’t be able to use only goto. At some point you will run into places where you either use other code which isn’t written like that, or you are at a location where the language structure forces you to do other stuff (make classes, methods, functions etc.). But technically, yes.
Should you do it however? Absolutely not. Goto programs are very hard to maintain, and as C# compiles into Intermediary Language, which uses jumps but on a higher level, you will probably lose a huge amount of performance when doing that. Also, the virtual machine can optimize a lot in “normal” code which it can’t when you put it in a fixed goto-schema.
Btw. your original code compiles into this IL, which is essentially what you wrote using goto (annotations by me):
// i = 0
IL_0001: ldc.i4.0 // Load integer value 0 to stack
IL_0002: stloc.0 // i // Store stack value in local variable 0
// goto loop-condition
IL_0003: br.s IL_0009 // Jump to IL_0009
// loop-start:
// i = i + 1
IL_0005: ldloc.0 // i // Load variable 0 to stack
IL_0006: ldc.i4.1 // Load integer `1` to stack
IL_0007: add // Add top two stack values
IL_0008: stloc.0 // i // Store result in local variable 0
// loop-condition:
// if (i < 10) { goto loop-start }
IL_0009: ldloc.0 // i // Load variable 0 to stack
IL_000A: ldc.i4.s 0A // Load integer `10` to stack
IL_000C: clt // Compare top two stack values
IL_000E: stloc.1 // CS$4$0000 // Store stack value in local variable 1
IL_000F: ldloc.1 // CS$4$0000 // Load variable 1 to stack
IL_0010: brtrue.s IL_0005 // Jump to IL_0005 if stack value is true