CareerCup (Bloomberg): Check if string is valid based on brackets
Guard conditions

ArgumentNullException is typically thrown on incorrect usage of the API. It is not an end-user exception, so I would not bother with an exception message.


  throw new ArgumentNullException("A string is required");


throw new ArgumentNullException(nameof(s)); // perhaps rename 's' to 'input' or 'value'


For the ArgumentException instances you throw, I would also add the nameof(parameterName) to the constructor. A decent error message is relevant here, so keep the message.

You have a guard on whitespace. I don't see this in the spec. Is this a requirement? If not, allow white space as either an open or close bracket.


  if (char.IsWhiteSpace(open) || char.IsWhiteSpace(close))


The next guard checks on duplicate registrations. An alternative policy is to ignore a registration if already registered. This depends on whether you want your API to be error-prone or act as a sandbox for consumers.


  if (openBrackets.Contains(open) || openBrackets.Contains(close))


I'm missing a guard condition. I doubt open and close can be the same.

if (open == close)  // throw ..


Readability

You could substitute some if statements with a ternary operator.

s = s ?? throw new ArgumentNullException(nameof(s));
validator = validator ?? BracketValidator.CreateDefaultValidator();


Redundant type declarations can be replaced by var. Unlike javascript, var is ok in C#.


  Stack&lt;char&gt; openStack = new Stack&lt;char&gt;();


var openStack = new Stack&lt;char&gt;();