2014-11-05 27 views
2

我正在写一个小VBA IDE插件,并有一个名为AssertClass一个COM可见的C#类,用AreEqual方法是这样的:如果我不想要类型安全?

public void AreEqual(object value1, object value2, string message = null) 
{ 
    if (value1.Equals(value2)) 
    { 
     AssertHandler.OnAssertSucceeded(); 
    } 
    else 
    { 
     AssertHandler.OnAssertFailed("AreEqual", message); 
    } 
} 

当客户端VBA代码调用像这样,预期所有作品:

'@TestMethod 
Public Sub TestMethod1() 
    'compares two identical Integer (Int16) values: 
    Assert.AreEqual 2, 2 
End Sub 

TestMethod1 passes

然而,当客户端VBA代码通过不同类型的,它失败:

'@TestMethod 
Public Sub TestMethod2() 
    'compares identically-valued Long (Int32) and Integer (Int16) values: 
    Assert.AreEqual CLng(2), 2 
End Sub 

TestMethod2 fails


TestMethod2通话Assert.AreEqual,在.NET代码接收intshort - 这是正确的......但我不想把它放在客户端的VBA代码上以确保它传递的是相同的类型 - 我希望所有这些调用导致成功的断言:

Assert.AreEqual CByte(2), 2 'fails 
Assert.AreEqual CInt(2), 2 'passes 
Assert.AreEqual CLng(2), 2 'fails 
Assert.AreEqual CSng(2), 2 'fails 
Assert.AreEqual CDbl(2), 2 'fails 
Assert.AreEqual CCur(2), 2 'fails 

毕竟,VBA是没有那么严格的C#,当涉及到类型安全和平等检查:

?CByte(2) = 2, CInt(2) = 2, CLng(2) = 2, CSng(2) = 2, CDbl(2) = 2, CCur(2) = 2 
True   True   True   True   True   True 

我怎样才能制定我AreEqual C#功能,从而...不知何故避免强迫在VBA客户端代码中输入安全性?我不能假设VBA客户端代码将传递数值 - 该方法还需要使用StringDate值。

我很难过。我唯一的选择是证明类型的问题

在VS 2013 Express中使用C#4.5。

+0

不要带走你想要完成的任何事情,也许这对你的设计完全不起作用,但为什么不用像'Assert.IsTrue()'这样更通用的方法呢?然后你的VBA示例应该可以工作:'Assert.IsTrue(CByte(2)= 2)' – TyCobb 2014-11-05 03:47:17

+0

@TyCobb AssertClass具有AreEqual,AreNotEqual,AreNotSame,AreSame,Fail,InConclusive ','IsFalse','IsNothing','IsNotNothing'和'IsTrue'方法。只有'AreEqual'(和'AreNotEqual')是有问题的;我忽略了其他的方法,以便brievety;) – 2014-11-05 03:49:33

回答

3

这是一个位在黑暗中拍摄的(没有用VBA & C#组合工作),但试试这个,看看它的工作原理:

public void AreEqual(object value1, object value2, string message = null) 
{ 
    bool convertedOk = true; 
    object value2Converted; 

    try 
    { 
     value2Converted = Convert.ChangeType(value2, value1.GetType()); 
    } 
    catch 
    { 
     convertedOk = false; 
    } 

    if (convertedOk && value1.Equals(value2Converted)) 
    { 
     AssertHandler.OnAssertSucceeded(); 
    } 
    else 
    { 
     AssertHandler.OnAssertFailed("AreEqual", message); 
    } 
} 

想法是,你改变第二类型价值,即第一,所以他们现在变得“比较”比较。

编辑: 按照评论建议的try/catch处理更新答案。谢谢!

+0

当然,将其转换! (facepalm)......现在,实际的修复需要一个“try/catch”块来确保转换确实是可能的,但是这个答案肯定会让我走上正确的轨道。谢谢! http://i.stack.imgur.com/IH72b。png – 2014-11-05 03:57:08

+0

有趣的答案。这可能需要包含在一个try块中,以防二值转换。 – RubberDuck 2014-11-05 03:57:28

+0

注意:在给它更多思想之后,我会保持类型安全的'AssertClass'方法。更简单得多,没有副作用,也没有边缘情况。考虑一下'AreEqual 300,CByte(30)'和'AreEqual CByte(30),300'--其中一个会爆炸,其他的通过。而且我甚至没有提及转换布尔值会发生什么。 – 2014-11-05 11:34:04