如何在一个返回值方法中使用try catch块?

7

我正在检查注册表单中上传的图像,需要使用try catch代码块。以下是我的代码:

public bool CheckFileType(string FileName)
{
        string Ext = Path.GetExtension(FileName);
        switch (Ext.ToLower())
        {
            case ".gif":                   
                return true;
                break;
            case ".JPEG":                    
                return true;
                break;
            case ".jpg":                  
                return true;
                break;
            case ".png":                   
                return true;
                break;
            case ".bmp":                   
                return true;
                break;
            default:                  
                return false;
                break;
        }

}

请建议我如何在这里使用try catch块。
提前致谢。

2
为什么需要“使用try catch块”?你到目前为止尝试了什么? - Richard
10
为什么你要使用 .JPEG 作为小写扩展名呢? - Ivan Crojach Karačić
6
你不必使用return break,因为return本身已经像break一样起到结束方法的作用。 - Simon Woker
这是一个糟糕代码的好例子。 - Christian
请不要捕获ArgumentNullException或NullReferenceException。那是一个错误。 - R. Martinho Fernandes
显示剩余5条评论
4个回答

9

最好这样做,

 public bool CheckFileType(string FileName)
 {
    bool result = false ;

    try
     {
      string Ext = Path.GetExtension(FileName);
      switch (Ext.ToLower())
      {
        case ".gif":                   
        case ".JPEG":                    
        case ".jpg":                  
        case ".png":                   
        case ".bmp":                   
            result = true;
            break;
       }

      }catch(Exception e)
      {
         // Log exception 
      }
      return result;
     }

@Henk:在你指出之前我已经注意到了,不管怎样,感谢你的及时友好提醒 ;) - Furqan Hameedi
1
将“.JPEG”与Ext.ToLower()进行比较不太可能匹配;) - Town
如何在这里使用try/catch?好的,你只需要将它们放入方法体中就可以了。我喜欢这个答案。 - username

7

有很多方法可以在返回值的方法中使用异常:

将返回语句放在try-catch外面,例如:

T returnValue = default(T);
try
{
    // My code
}
catch 
{
    // Exception handling code
}
return returnValue;

在catch语句中加入一个返回语句。
try
{
    // My code
}
catch 
{
    // Handle exception
    return default(T);
}

抛出异常

您不必返回值,方法只需结束(例如到达return语句或throw语句)。根据异常的类型,返回值可能并不总是有效的。

您应该仔细考虑何时以及如何捕获和处理异常:

  1. 有什么可能失败?
  2. 为什么/如何会失败?
  3. 失败时我应该怎么做?

在您的情况下:

  1. 唯一可能失败的语句是string Ext = Path.GetExtension(FileName);,根据文档,如果FileName包含这些字符,则可能会失败。 (请注意,即使FileName为空,GetExtension也不会返回null)。
  2. 如果用户提供的字符串包含这些无效字符,则可能会发生这种情况。
  3. 如果发生这种情况,我猜我们应该返回false,表示路径无效(但这取决于应用程序)。

因此,我可能会像这样处理异常:

public bool CheckFileType(string FileName)
{
    string Ext;
    try
    {
        Ext = Path.GetExtension(FileName);
    }
    catch (ArgumentException ex)
    {
        return false;
    }
    // Switch statement
}

请注意,我们只捕获预期的异常(ArgumentException),并且只在我们期望抛出异常的语句周围放置try语句。
事实上,尽可能避免抛出和捕获异常是一个好主意——它们不仅会产生性能损失(如果该方法在循环内部调用,则可能导致严重问题),而且您可能会意外地捕获和处理未预期的异常,掩盖了更严重的问题。
在这种情况下,我们可以通过检查FileName是否包含任何无效字符来完全避免抛出异常。
public bool CheckFileType(string FileName)
{
    if (FileName == null)
    {
        return false;
    }
    if (FileName.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0)
    {
        return false;
    }
    // Your original method goes here
}

我不喜欢捕获“ArgumentException”。我更喜欢用if检查文件名是否包含无效字符。除此之外,回答很好。+1。 - R. Martinho Fernandes
我认为,在这种特定情况下,如果出现错误,它应该沿着堆栈向上传递,而不是在此方法中被捕获或处理。 - data
@Martinho 嘿,我在你发布这条消息的时候刚好在添加 :-) - Justin
很遗憾(只是阅读):“从该方法返回的数组不能保证包含文件和目录名称中无效的完整字符集。” :( - R. Martinho Fernandes
@data_smith 这取决于应用程序-在这种情况下,我会说自己检查或允许异常被抛出都可以,捕获/屏蔽异常较少使用,但无论如何我仍然展示了它,因为在许多情况下你无法避免异常被抛出(例如在IO中),并且它展示了如何考虑异常(可能会抛出什么?为什么会抛出?我该怎么做?) - Justin
@Martinho 是的,但是 GetExtension 方法说明只有当字符串包含由该方法返回的字符时才会抛出异常——我可以假设对于不在该列表中的无效字符它不会抛出异常(因为没有进行磁盘 IO 操作,所以它不需要抛出异常)。此外,如果提供了这样的字符,允许引发异常可能是两害中较小的一个。 - Justin

2

由于您实际上并没有测试文件类型(只测试了文件名的扩展名),因此我建议首先更改方法名称。您可以创建一个扩展方法来处理它:

public static bool HasImageExtension(this string fileName)
{
    try
    {
        if (fileName == null) return false;

        string[] validExtensions = new string[] { ".gif", ".jpg", ".jpeg", ".png", ".bmp" };

        string extension = Path.GetExtension(fileName);
        return validExtensions.Contains(extension);
    }
    // catch the specific exception thrown if there are 
    // invalid characters in the path
    catch (ArgumentException ex) 
    {
        // do whatever you need to do to handle 
        // the fact there are invalid chars
        throw; 
    }
}

然后您可以这样调用:

string fileName = "testFileName.jpg";
bool hasImageExtension = fileName.HasImageExtension();

实际上,如果路径包含无效字符,Path.GetExtension也可能会抛出异常。 - vgru
@Groo:没错,你说得对 - 完全破坏了我的答案,是时候更新一下了 ;) - Town

0

这应该可以工作:

public bool CheckFileType(string FileName)
{
    try
    {
        string Ext = Path.GetExtension(FileName).ToLower();
        string[] okExt = ".gif|.jpg|.jpeg|.png|.bmp".Split('|');

        foreach(var item in okExt)
        {
            if(Ext == item)
                return true;
        }
        return false;
    }
    catch(Exception ex)
    {
        throw;
    }
}

并且要记住:永远不要捕获你无法处理的异常。(或者至少重新抛出它们)

1
否则,我缺少的是return false; - merxbj
修复了上述提到的问题。 - data
或者,您可以使用 LINQ: return ".gif|.jpg|.jpeg|.png|.bmp".Split('|').Any(e => e.Equals(Ext)); - vgru
我认为这样可能更清晰:return new List<string> { ".gif", ".jpeg", ".jpg", ".png", ".bmp" }.Contains(ext); - Chris McAtackney
遗憾的是,LINQ并不总是可用的,在这种情况下,使用LINQ并不能带来太多好处。 - data

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接