2014-11-05 1 views
2

Я пишу немного IDE VBA надстройки, и есть COM-видимый C# класс называется AssertClass, с 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 получает int и short - что правильно ... но я не хочу поставить его на код 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 будет передавать числовые значения - метод должен также работать с значениями String и Date.

Я в тупике. Я единственный вариант, чтобы зафиксировать тот факт, что типов вопросов?

Использование C# 4.5 в VS 2013 Express.

+0

Не забирать все, что вы пытаетесь выполнить, и, возможно, это вообще не работает для вашего дизайна, но почему бы не использовать более общий метод, например 'Assert.IsTrue()'? Затем ваши примеры VBA должны работать: 'Assert.IsTrue (CByte (2) = 2)' – TyCobb

+0

@TyCobb 'AssertClass' имеет' AreEqual', 'AreNotEqual',' AreNotSame', 'AreSame',' Fail', 'Inconclusive ',' IsFalse', 'IsNothing',' IsNotNothing' и 'IsTrue'. Только 'AreEqual' (и' AreNotEqual') проблематичны; Я опустил другие методы для brievety;) –

ответ

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); 
    } 
} 

Идея в том, что вы измените тип второго значение, которое сначала, поэтому они теперь стали более «сопоставимыми» для сравнения.

EDIT: Обновленный ответ с обработкой try/catch, как это предлагается комментариями. Благодаря!

+0

Конечно, преобразуйте! (facepalm) ... теперь фактическое исправление требует блока 'try/catch', чтобы гарантировать, что преобразование действительно возможно, но этот ответ определенно поставил меня на правильный путь. Благодаря! http://i.stack.imgur.com/IH72b.png –

+0

Интересный ответ. Это, вероятно, нужно будет обернуть в блок try в случае, если значение два не может быть преобразовано. – RubberDuck

+0

Замечание: после того, как он еще немного подумал, я сохраню методы 'AssertClass' типа безопасными. Многое, намного проще, никаких побочных эффектов, и никаких случаев кромки. Рассмотрим 'AreEqual 300, CByte (30)' против 'AreEqual CByte (30), 300' - один разрывается, другой проходит. И я даже не упоминаю, что происходит с преобразованными значениями 'Boolean'. –