'TryAction()'方法是邪恶的吗?

时间:2012-06-15 19:08:32

标签: vb.net pass-by-reference fxcop

我正在努力改进我的代码中的FxCop合规性(这是有史以来第一次),但我有点陷入道德问题。我有一个方法GetText()从远程服务器返回一个字符串,但在某些情况下可以抛出异常。这就是为什么我还有一个方法TryGetText(ByRef text As String),它返回一个布尔值,表示调用是否成功。如果为true,则将返回值分配给text变量。

我认为这种结构是完全可以接受的,考虑到甚至微软都这样做(例如Integer.TryParse)。 尽管如此,FxCop还是啧啧称道,指责“你不能通过引用传递!”

为了绕过这个警告(并且有很多这样的警告),我用StringBuilder替换了参数。但是,尽管现在符合要求,我认为它不会以任何方式改进我的代码。

在:

    Public Function TryGetText(ByRef text As String) As Boolean
        Dim command As New GetTextCommand(Me)
        Dim result As CommandResult = ProcessCommand(command, True)
        If result.CommandStatus <> Constants.Status.Failed Then
            text = result.Text
            Return True
        Else
            Return False
        End If
    End Function

后:

    Public Function TryGetText(builder As Text.StringBuilder) As Boolean
        Dim command As New GetTextCommand(Me)
        Dim result As CommandResult = ProcessCommand(command, True)
        If result.CommandStatus <> Constants.Status.Failed Then
            builder.Clear()
            builder.Length = result.Text.Length
            builder.Append(result.Text)
            Return True
        Else
            Return False
        End If
    End Function

这是ByRef的可接受使用,还是我应该使用stringbuilder替代?我对使用这个结构的每个方法抑制此警告感觉不太舒服。我不觉得stringbuilder变种也改善了代码的可用性。

4 个答案:

答案 0 :(得分:2)

这可能是ByRef的好用,所以我倾向于为该案例添加例外。如果您在Visual Studio中使用代码分析功能,则只需将以下属性添加到方法中即可:

<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")> _
Public Function TryGetText(ByRef text As String) As Boolean

答案 1 :(得分:2)

在创建线程安全类之类的东西时,TryAction方法非常有用。它将两个步骤(测试和操作)组合成单个原子操作。 Microsoft在Concurrent集合类中大量使用它。例如http://msdn.microsoft.com/en-us/library/dd287191.aspx#Y0

所以我认为“你不能通过引用传递”的一揽子声明。在所有情况下都不应被视为福音。有合法用途。在您的特定情况下,ByRef似乎比StringBuilder版本更不笨拙。但是如果在当前返回false的情况下返回null / Nothing的简单string GetText()是等效的,那么这似乎是最好的。

答案 2 :(得分:0)

嗯,我想每个人都讨厌过多的反对意见。两个已经太多了。虽然在你的情况下有很多方法,他们都遵循相同的模式听起来不是一个真正的问题。 您可以选择不遵守Microsoft的Try *方法模式。

而不是布尔值,为什么不在成功时返回字符串,如果失败则返回Nothing / Empty? 然后,您可以使用String.IsNullOrEmpty(resultText)测试TryGetText输出。

确实,这是更多的代码,但它确实解决了警告(如果这真的是你所追求的那样)。

答案 3 :(得分:0)

当您尝试在功能样式中使用方法时,通过引用传递会使事情变得复杂。您可以考虑使用可空类型或元组或您自己的选项类型。

由于我不熟悉VB,这里有一个C#示例:

struct Option<T> {
   public bool ContainsElement { get; private set; }
   private T element;
   public T Element {
      get {
         if (!ContainsElement) throw new NoElementException ();
         return element;
      }
      set {
         element = value;
         ContainsElement = true;
      }
   }
   public T GetElementOrDefault (T defaultValue) {
      return ContainsElement ? element : defaultValue;
   }
}

Option<string> GetText () {
   ...
}