Inspired by this question, I decided to give it a try and implemented a brainfuck interpreter myself. It includes various improvements:It's object-oriented and modularUnlimited tape sizeIt includes a call stack (no seeking for opening parenthesis)It allows stepping and debuggingIt throws exceptions on errorsTape/// <summary>/// One-sided, infinite, default-initialized Tape. </summary>public class Tape<T>{    List<T> _tape;    int _pos;    public Tape()    {        _tape = new List<T>();        _tape.Add(default(T));        _pos = 0;    }    /// <summary>    /// Currently selected cell's value. </summary>    public T Value    {        get        {            return _tape[_pos];        }        set        {            _tape[_pos] = value;        }    }    /// <summary>    /// Step one cell to the left. </summary>    public void StepLeft()    {        if (_pos == 0)            throw new InvalidOperationException();        else            _pos--;    }    /// <summary>    /// Step one cell to the right. </summary>    public void StepRight()    {        _pos++;        if (_pos == _tape.Count)            _tape.Add(default(T));    }    /// <summary>    /// Return a full snapshot of the tape without altering anything. </summary>    public T[] ToArray()    {        return _tape.ToArray();    }}Interpreterpublic class BrainfuckInterpreter{        Stream _program;    Stream _input;    Stream _output;    Tape<byte> _tape;    Stack<long> _callStack;    /// <summary>    /// Create a new BrainfuckInterpreter. </summary>    /// <param name=program>    /// Program to be executed. Must be readable and seekable.    /// <param name=input>    /// Must be readable. Can be null if the program doesn't take any input. </param>    /// <param name=output>    /// Must be writable. Can be null if the program doesn't produce output. </param>    public BrainfuckInterpreter(Stream program, Stream input, Stream output)    {        _program = program;        _input = input;        _output = output;        _tape = new Tape<byte>();        _callStack = new Stack<long>();    }    /// <summary>    /// Run the program until it terminates. </summary>    public void Run()    {        while (Step());    }    /// <summary>    /// Execute the next command. </summary>    /// <returns>    /// False if the program terminated. True otherwise. </returns>    public bool Step()    {        int command = _program.ReadByte();        switch (command)        {            default: throw new ArgumentException(); // Invalid command            case -1: return false; // End reached            case '+': _tape.Value++; break;            case '-': _tape.Value--; break;            case ',':                int input = _input.ReadByte();                if (input == -1) // Null-termination instead of error status                    _tape.Value = 0;                else                    _tape.Value = (byte)input;                break;            case '.': _output.WriteByte(_tape.Value); break;            case '>': _tape.StepRight(); break;            case '<': _tape.StepLeft(); break;            case '[': _callStack.Push(_program.Position); break;            case ']':                if (_tape.Value == 0)                    _callStack.Pop();                else                    _program.Position = _callStack.Peek();                break;        }        return true;    }    /// <summary>    /// Print the tape for debug purposes.    /// Format (hex): |XX|XX|XX|...|XX| </summary>    public string Print()    {        string result = |;        foreach (var n in _tape.ToArray())        {            result += String.Format({0:X2}|, n);        }        return result;    }}Main routine (for testing)Takes the program directly (not a filename) as first command line argument. Prints the tape's contents to stderr after each step.public static class Program{    public static void Main(string[] args)    {        Stream program = new MemoryStream(args[0].Select(c => (byte)c).ToArray());        var bf = new BrainfuckInterpreter(            program,            Console.OpenStandardInput(),            Console.OpenStandardOutput()        );        while (bf.Step())        {            Console.Error.WriteLine(bf.Print());        }    }}
Object-oriented Brainfuck interpreter
c#;interpreter;brainfuck
switch (command){        case '[': _callStack.Push(_program.Position); break;    case ']':        if (_tape.Value == 0)            _callStack.Pop();        else            _program.Position = _callStack.Peek();        break;}A call stack in a tape-based language?  Heresy!Seriously, though, the code is wrong.  You have implemented a do {  } while (_tape.Value != 0) loop instead of a while (_tape.Value != 0) {  } loop.