简体   繁体   English

C# 中的默认结构不调用隐式运算符

[英]Implicit operator isn't called for default of struct in C#

I'm implementing a C# variant of Haskell's Maybe and came across a weird issue where null and default has different implication on the value returned from an implicit conversion.我正在实施 Haskell 的 Maybe 的 C# 变体,遇到一个奇怪的问题,其中nulldefaultimplicit转换返回的值有不同的含义。

public class TestClass
{
    public void Test()
    {
        Maybe<string> valueDefault = default;
        Maybe<string> valueNull = null;
        Maybe<string> valueFoobar = "foobar";
        Console.WriteLine($"Default: (Some {valueDefault.Some}, None {valueDefault.None}");
        Console.WriteLine($"Null: (Some {valueNull.Some}, None {valueNull.None}");
        Console.WriteLine($"Foobar: (Some {valueFoobar.Some}, None {valueFoobar.None}");
    }
}

public struct Maybe<T>
{
    public T Some { get; private set; }
    public bool None { get; private set; }

    public static implicit operator Maybe<T>(T value)
    {
        return new Maybe<T>() {
            Some = value,
            None = value == null
        };
    }
}

The output being: output 是:

Default: (Some, None False)默认值:(一些,无假)

Null: (Some, None True) Null:(一些,不正确)

Foobar: (Some foobar, None False) Foobar:(一些foobar,没有假)

I was expecting both valueDefault and valueNull to be equal.我期望valueDefaultvalueNull相等。 But seems that null is converted while default isn't.但似乎null已转换,而default值未转换。 I fixed the issue by replacing None with HasSome with a reversed boolean condition, but still the question remains.我通过将 None 替换为具有反向 boolean 条件的 HasSome 来解决问题,但问题仍然存在。

Why is null and default treated differently?为什么 null 和 default 被区别对待?

Every type has a default value, including Maybe<T> .每种类型都有一个默认值,包括Maybe<T> See this page for a list.请参阅此页面以获取列表。

Maybe<string> valueDefault = default; will assign the default value of Maybe<string> to valueDefault .会将Maybe<string>的默认值分配给valueDefault What's the default value of Maybe<string> ? Maybe<string>的默认值是多少? According to that page, since Maybe<string> is a struct, its default value is:根据那个页面,因为Maybe<string>是一个结构,它的默认值是:

The value produced by setting all value-type fields to their default values and all reference-type fields to null.通过将所有值类型字段设置为其默认值并将所有引用类型字段设置为 null 生成的值。

So it's an instance of Maybe<string> with Some being null and None being false .所以它是Maybe<string>的一个实例,其中SomenullNonefalse false is the default value of bool . falsebool的默认值。

The compiler doesn't try to use the default value of string , since that requires a further conversion to Maybe<string> .编译器不会尝试使用string的默认值,因为这需要进一步转换为Maybe<string> If it can just use the default value of Maybe<string> , why go the extra trouble, right?如果它可以直接使用Maybe<string>的默认值,为什么 go 会很麻烦,对吧?

You can force it to though:你可以强制它:

Maybe<string> valueDefault = default(string);

null , on the other hand, gets converted to Maybe<string> because null is not a valid value of Maybe<string> (structs can't be null,), so the compiler deduces that you must mean null as string , and does the implicit conversion.另一方面, null被转换为Maybe<string>因为null不是Maybe<string>的有效值(结构不能是 null,),因此编译器推断您必须null as string ,并且确实隐式转换。


You might know this already, but you seem to be reinventing Nullable<T>您可能已经知道这一点,但您似乎正在重新发明Nullable<T>

default always fills the memory of the struct with zero bytes. default总是用零字节填充结构的 memory。 null is not a valid value for a value type, so the compiler discovers the implicit (Maybe<string>)(string)null cast. null不是值类型的有效值,因此编译器发现隐式(Maybe<string>)(string)null转换。

Perhaps you could replace with;也许您可以替换为;

public struct Maybe<T>
{
    public T Some { get; private set; }
    public bool None => Some == null;
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM