我正在尝试建立一个行为类似于Nullable<T>
的类,特别是无需显式调用Nullable<T>
即可访问nullable.Value
类的基础值的方式。
在以下示例中,行check1
和check2
均起作用。
Nullable<DateTime> nullable = new DateTime();
bool check1 = nullable >= DateTime.Now; //Works
bool check2 = nullable.Value >= DateTime.Now; //Works
我建立了自己的类
TrackedValue
,该类可以记住包装的值是否已更改。我基于Nullable<T>
建立了隐式和显式运算符。Nullable<T>
定义public struct Nullable<T> where T : struct
{
public Nullable(T value);
public static explicit operator T(T? value);
public static implicit operator T?(T value);
...
}
TrackedValue<T>
定义public class TrackedValue<T> : IChangeTracking
{
...
T trackedValue;
public T Value
{
get
{
return this.trackedValue;
}
set
{
this.trackedValue = value;
}
}
public static explicit operator T(TrackedValue<T> value)
{
return value.Value;
}
public static implicit operator TrackedValue<T>(T value)
{
return new TrackedValue<T>() { Value = value };
}
}
因此,我期望以下内容能正常工作,但是
check3
由于以下原因而无法编译:Argument 1: cannot convert from 'TrackedValue<System.DateTime>' to 'System.DateTime'
TrackedValue<DateTime> trackedValue = new DateTime();
bool check3 = trackedValue >= DateTime.Now; //Does not work
bool check4 = trackedValue.Value >= DateTime.Now; //Works
任何指针将不胜感激。
最佳答案
该行特别不起作用,因为它需要implicit
转换,但是您已将其标记为explicit
。
public class TrackedValue<T> : IChangeTracking
{
T trackedValue;
public T Value
{
get
{
return this.trackedValue;
}
set
{
this.trackedValue = value;
}
}
public static implicit operator T(TrackedValue<T> value)
{
return value.Value;
}
public static implicit operator TrackedValue<T>(T value)
{
return new TrackedValue<T>() { Value = value };
}
}
但是自然地,您想模仿
Nullable<T>
模型。那么,为什么Nullable<T> <= T
隐式工作而不是您的隐性工作?我相信它来自C#编译器本身。埃里克·利珀特(Eric Lippert)关于如何编译/优化Nullables的excellent blog series。据我了解,编译器本身将编写的代码/ IL完全更改为不同的指令集。埃里克(Eric)在该系列上的third entry开始证明这一点。这是因为我相信一般情况下它会处理null的特殊情况。
我不确定您是否可以解决此问题,但是最简单的方法可能只是将那里的一个转换运算符标记为
implicit
,并希望它不会对您造成任何有关和TrackedValue<T>
。编辑:那些不一致的项目之一将是说如何进行比较。
如果
Nullable<T>
是bool check3 = trackedValue >= DateTime.Now
,请考虑您的行trackedValue
。对于null
来说,它就像这样(请注意,这并不完全相同,请参阅Eric的系列文章。这只是为了传达概念):check3 = trackedValue.HasValue ? trackedValue.Value >= DateTime.Now : false;
编译器甚至避免调用转换运算符。另一方面,您的尝试运行隐式转换(假设您将其切换为隐式),这可能导致
Nullable<DateTime>
被皱眉(隐式运算符不应抛出异常)。 NullReferenceException
将转换运算符定义为Nullable<T>
的原因是,对于那些您直接进行转换的时间(例如explicit
),如果该值为null,则可能引发异常。关于c# - 建立行为类似于Nullable <T>的类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16608685/