Remove all duplicated elements in a single list
All in all it looks OK to me. I would maybe call the variables something else:

list -&gt; root
tmp -&gt; currentValue
start -&gt; result
etc.




In the ListNode class it's common practice in C# to name public members in CamelCase:

public class ListNode
{
    public int Value;
    public ListNode Next;
    public ListNode(int x)
    {
         val = x;
         next = null;
    }
}




I think that the null-conditional operator is unnecessary in the outer loop.



My own version would look something like:

public static ListNode RemoveDuplicates(ListNode root)
{
  ListNode current = root;
  ListNode result = null;
  ListNode prev = null;

  while (current != null)
  {
    bool singleFound = true;

    while (current?.val == current?.next?.val)
    {
      current = current.next;
      singleFound = false;
    }

    if (singleFound)
    {
      if (result == null)
      {
        result = prev = current;
      }
      else
      {
        prev.next = current;
        prev = prev.next;
      }
    }

    current = current?.next;

    if (singleFound &amp;&amp; prev != null)
      prev.next = null;
  }

  return result;
}




Some other considerations:

The name is maybe ambiguous:

My first thought was that it should remove all but one entry per value:

{ 1, 1, 2, 3, 4, 5, 5, 7, 7 } -&gt; { 1, 2, 3, 4, 5, 7 }




Normally I would prefer that a static method/function would leave the argument list untouched, but you actually operate on the nodes in the list directly and return a new ListNode as root of the resulting list. So the original list is in an indefinite state 
when the function returns.

My own implementation modified to handle that:

public static ListNode RemoveDuplicates(ListNode root)
{
  ListNode current = root;
  ListNode result = null;
  ListNode prev = null;

  while (current != null)
  {
    bool singleFound = true;

    while (current?.val == current?.next?.val)
    {
      current = current.next;
      singleFound = false;
    }

    if (singleFound)
    {
      if (result == null)
      {
        result = prev = new ListNode(current.val);
      }
      else
      {
        prev.next = new ListNode(current.val);
        prev = prev.next;
      }
    }

    current = current?.next;
  }

  return result;
}


If you had a class like:

public class SortedLinkedList
{
  public void DeleteDuplicates()
  {
    ...
  }
}


I would on the other hand expect DeleteDuplicates() to operate on the current instance.