&quot;[...] Project, like many types in Roslyn, is immutable. When we add a Document to a project, we aren’t changing [the] project. We create a new one that can be accessed through the new returned Document. This snippet illustrates the example.<p>1 var doc = project.AddDocument(&quot;TestFile.cs&quot;, cSharpText);
 2 Debug.Assert(!project.ContainsDocument(doc.Id));
 3 Debug.Assert(doc.Project.ContainsDocument(doc.Id));<p>Roslyn confused me when it threw away my changes until I would notice the return type of the method and realize that adding a document doesn&#x27;t modify a project but creates a new one.&quot;<p>I love functional datatypes, but this is a poorly designed API.<p>First off, functional new-version operations -- that return a new instance rather than modifying the existing one in place -- should when possible be named with nouns or prepositions rather than verbs.  For example, the addition operation on Java&#x27;s BigInteger should be named &#x27;plus&#x27;, not &#x27;add&#x27;.  If you write<p><pre><code>  x.add(y);
</code></pre>
and don&#x27;t happen to recall that BigInteger is a functional type, it&#x27;s easy to assume that this statement modifies &#x27;x&#x27; by adding &#x27;y&#x27; to it.  But if you write<p><pre><code>  x.plus(y);
</code></pre>
the name itself suggests that this is an expression whose value you care about and want to assign to a variable instead of discarding.<p>I would have called this operation &#x27;WithDocument&#x27; rather than &#x27;AddDocument&#x27;.<p>And secondly, having this operation return the <i>document</i> rather than the new project seems a bit weird.  I see the reason for it -- the new document object is being created at the same time from the source file supplied -- but it would be cleaner for this to be two operations (create the document, then create the new version of the project).  If that doesn&#x27;t work for some reason, I would use an out parameter to return the new document.