Sonarqube就是一个不会烦的“好同事”,每一行代码有没有bugs,有没有坏味道,都能查得一清二楚,再“恶心”代码也能在sonarqube的调教下变得更加优质。今天见到两个 Using嵌套的写法,看起来没有什么问题,但是sonarqube还是提示坏味道。来看看怎么回事吧!
第一种写法
using (FileStream fs = new FileStream(GetPath(fileName), FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite, 1024))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.WriteLine("hello world");
sw.Flush();
sw.Close();
}
fs.Close();
}
第二种写法
using (FileStream fs = new FileStream(GetPath(fileName), FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite, 1024))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.WriteLine("hello world");
sw.Flush();
}
}
无论是第一种写法,还是第二种写法,sonarqube都会提示:
A proper implementation of IDisposable.Dispose should allow for it to be called multiple times on the same object, however this is not guaranteed and could result in an exception being thrown.
It is best not to rely on this behaviour and therefore make sure an object is disposed only once on all execution paths. This is particularly true when dealing with nested using statements.
Refactor this code to make sure 'fs' is disposed only once.
sonarqube给出的参考提示:
Noncompliant Code Example
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream)) // Noncompliant: 'stream' will be disposed twice
{
// Use the writer object...
}
}
Compliant Solution
Stream stream = null; try { stream = new FileStream("file.txt", FileMode.OpenOrCreate); using (StreamWriter writer = new StreamWriter(stream)) { stream = null; // Use the writer object... } } finally { if(stream != null) stream.Dispose(); }
有没有感觉按sonarqube提示改完之后,都有一种“改错”的感觉,改完之后,代码看起来没有之前美观了~
进来就设置为null,后面能成功?赶紧来看小实验。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
private static string directory = System.Configuration.ConfigurationSettings.AppSettings["Directory"];
static void Main(string[] args)
{
StoreFile();
ReadFile("txt.txt");
Console.ReadLine();
}
/// <summary>
/// 获取完整路径
/// </summary>
/// <returns>完整路径</returns>
private static string GetPath(string fileName)
{
if (directory[directory.Length - 1].Equals('\\'))
{
return string.Format("{0}{1}", directory, fileName);
}
else
{
return string.Format("{0}\\{1}", directory, fileName);
}
}
public static void StoreFile()
{
FileStream fs = null;
try
{
fs = new FileStream(GetPath("txt.txt"), FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite, 1024);
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
{
fs = null;
sw.WriteLine("hello world!");
sw.Flush();
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
public static void ReadFile(string fileName)
{
FileStream fs = null;
try
{
fs = new FileStream(GetPath(fileName), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024);
using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
{
fs = null;
Console.WriteLine(sr.ReadToEnd());
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
}
}
实验显示,按sonarqube提示调整完代码后,文件读写正常
后记:推荐一下sonarqube,能扫描代码,并从bugs、坏味道、重复率三个维度给出代码质量结果,内置N种代码规范,有效提升团队代码质量!从程序自动检查代码!
有没有心动的感觉,赶紧行动起来,为自己的团队部署一下sonarqube,开启一场惊天动地的代码质量优化之旅吧!