public static void Main(string[] args)
int count = theFoo.Accept(new CountVisitor());
string name = theFoo.Accept(new NameVisitor());
public interface IVisitor<out TResult, in TVisitable> where TVisitable : IVisitable<TVisitable>
TResult Visit(TVisitable visitable);
public interface IVisitable<out TVisitable> where TVisitable : IVisitable<TVisitable>
TResult Accept<TResult>(IVisitor<TResult, TVisitable> visitor);
public class Foo : IVisitable<Foo>
public TResult Accept<TResult>(IVisitor<TResult, Foo> visitor) => visitor.Visit(this);
public class CountVisitor : IVisitor<int, Foo>
public int Visit(Foo visitable) => 42;
public int Visit(Bar visitable) => 7;
public class NameVisitor : IVisitor<string, Foo>
public string Visit(Foo visitable) => "Chewie";
public class Bar : IVisitable<Bar>
public TResult Accept<TResult>(IVisitor<TResult, Bar> visitor) => visitor.Visit(this);