I have the following two records:
internal record Token
{
private string content;
public string Content
{
get => content;
init => content = value ?? throw new ArgumentNullException(nameof(Content));
}
public int Position { get; init; }
public Token(string content, int position)
{
Content = content ?? throw new ArgumentNullException(nameof(content));
Position = position;
}
public override string ToString()
{
return Content;
}
public static implicit operator string(Token token)
{
return token.Content;
}
}
internal record CommaToken : Token
{
public CommaToken(int position) : base(",", position)
{
}
}
and when I do:
CommaToken comma = new(0);
Console.WriteLine(comma);
it just outputs this:
,
According to the docs, a record should have a compiler-synthesized ToString method unless another method with the same signature is defined. In my case, CommaToken
doesn't have a ToString method defined, so it should use its own synthesized ToString instead of the one in Token
. What have I done wrong?
It turns out that Console.WriteLine
also accepts a string, so the compiler decided to use the public static implicit operator string(Token token)
to cast CommaToken
into a string, which caused the problem.
I then learned that a conversion operator should be marked as explicit if the conversion will discard information of some type. In my case, casting a Token
to a string
is throwing away some information, so the conversion operator should be marked as explicit.