我有一个Money带有隐式转换的简单类型decimal:
struct Money
{
decimal innerValue;
public static implicit operator Money(decimal value)
{
return new Money { innerValue = value };
}
public static explicit operator decimal(Money value)
{
return value.innerValue;
}
public static Money Parse(string s)
{
return decimal.Parse(s);
}
}
Run Code Online (Sandbox Code Playgroud)
我定义了一个Sum()重载来操作这些值:
static class MoneyExtensions
{
public static Money Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Money> selector)
{
return source.Select(x => (decimal)selector(x)).Sum();
}
}
Run Code Online (Sandbox Code Playgroud)
我没想到的是这种扩展方法会干扰现有的Sum()扩展方法:
var source = new[] { "2" };
Money …Run Code Online (Sandbox Code Playgroud) 我创建了一个自定义结构来表示金额.它基本上是一个包装器decimal.它有一个隐式转换运算符将其强制转换为decimal.
在我的单元测试中,我断言Amount等于原始十进制值,但测试失败.
[TestMethod]
public void AmountAndDecimal_AreEqual()
{
Amount amount = 1.5M;
Assert.AreEqual(1.5M, amount);
}
Run Code Online (Sandbox Code Playgroud)
当我使用int(我没有创建转换运算符)时,测试确实成功.
[TestMethod]
public void AmountAndInt_AreEqual()
{
Amount amount = 1;
Assert.AreEqual(1, amount);
}
Run Code Online (Sandbox Code Playgroud)
当我悬停时AreEqual,它显示第一个解析为
public static void AreEqual(object expected, object actual);
Run Code Online (Sandbox Code Playgroud)
而第二个导致
public static void AreEqual<T>(T expected, T actual);
Run Code Online (Sandbox Code Playgroud)
看起来这个int值1是隐式地转换为a Amount,而decimal值1.5M则不是.
我不明白为什么会这样.我本来希望恰恰相反.第一次单元测试应该能够投射decimal到Amount.
当我添加隐式强制转换int(没有意义)时,第二个单元测试也会失败.因此,添加隐式强制转换运算符会破坏单元测试.
我有两个问题:
Amount结构,以便两个测试都能成功?(我知道我可以改变测试来做一个明确的转换,但如果我不是绝对必须,我不会)
我的Amount结构(只是一个显示问题的最小实现)
public struct Amount …Run Code Online (Sandbox Code Playgroud) 我将试着用一个例子来解释我的问题:
class V<T>
{
public readonly Func<T> Get;
public readonly bool IsConstant;
V(Func<T> get, bool isConstant)
{
Get = get;
IsConstant = isConstant;
}
public static implicit operator V<T>(T value)
{
return new V<T>(() => value, true);
}
public static implicit operator V<T>(Func<T> getter)
{
return new V<T>(getter, false);
}
}
void DoSomething<T>(V<T> v)
{
//...
}
void Main()
{
DoSomething<string>("test"); // (1) type inference is not working
DoSomething<string>((V<string>)(() => "test")); // (2) implicit operator does not work
}
Run Code Online (Sandbox Code Playgroud)
在方法中 …