55

长话短说:我发现Java 反模式是不可或缺的资源。对于初学者和专业人士一样。我还没有为 C# 找到类似的东西。所以我会以社区 wiki 的形式公开这个问题,并邀请大家分享他们的知识。由于我是 C# 新手,我对此非常感兴趣,但不能从一些反模式开始:/

以下是我发现特别适用于 C# 而不是其他语言的答案。

我只是复制/粘贴这些!考虑看看这些评论。


投掷NullReferenceException

抛出错误的异常:

if (FooLicenceKeyHolder == null)
    throw new NullReferenceException();

属性与公共变量

类中的公共变量(使用属性代替)。

除非该类是一个简单的数据传输对象。


不理解 bool 是一种真正的类型,而不仅仅是一种约定

if (myBooleanVariable == true)
{
    ...
}

或者,甚至更好

if (myBooleanVariable != false)
{
    ...
}

像这样的结构经常被开发人员使用CC++其中布尔值的概念只是一种约定(0 == false,其他任何东西都是 true);在 C# 或其他具有真正布尔值的语言中,这不是必需的(或可取的)。


使用using()

在适当的地方不使用using

object variable;
variable.close(); //Old code, use IDisposable if available.
variable.Dispose(); //Same as close.  Avoid if possible use the using() { } pattern.
variable = null; //1. in release optimised away.  2. C# is GC so this doesn't do what was intended anyway.
4

38 回答 38

62

错误地重新抛出异常。重新抛出异常:

try
{
    // do some stuff here
}
catch (Exception ex)
{
    throw ex;  // INCORRECT
    throw;     // CORRECT
    throw new Exception("There was an error"); // INCORRECT
    throw new Exception("There was an error", ex); // CORRECT
}
于 2009-10-07T05:30:01.743 回答
40

GC.Collect()收集而不是信任垃圾收集器。

于 2009-10-07T05:25:41.033 回答
30

我在 Java 和 C# 中都看到了太多这种情况......

if(something == true){
  somethingelse = true;
}

如果它也有奖励积分

else{
  somethingelse = false;
}
于 2009-10-07T05:55:42.957 回答
25
using Microsoft.SharePoint;

'纳夫说

于 2009-10-09T12:35:42.727 回答
22

我经常看到以下代码:

if (i==3)
       return true;
else
       return false;

应该:

       return (i==3);
于 2009-10-08T13:16:23.250 回答
17

侮辱得墨忒耳定律:

a.PropertyA.PropertyC.PropertyB.PropertyE.PropertyA = 
     b.PropertyC.PropertyE.PropertyA;
于 2009-10-07T05:27:20.407 回答
17

投掷NullReferenceException

if (FooLicenceKeyHolder == null)
    throw new NullReferenceException();
于 2009-10-07T05:34:51.827 回答
16

这是真的,我亲眼所见。

public object GetNull()
{
     return null;
}

它实际上是在应用程序中使用的,甚至还有一个与之配套的存储过程,一个返回 null 的 sp_GetNull....

这让我很开心。

我认为 sp 用于经典的 asp 站点 .. 与结果集有关。.net 是有人将代码“转换”为 .net 的想法......

于 2009-10-07T20:00:31.663 回答
14
int foo = 100;
int bar = int.Parse(foo.ToString());

或者更一般的情况:

object foo = 100;
int bar = int.Parse(foo.ToString());
于 2009-10-07T05:20:35.647 回答
12

我在我们的项目中发现了这个,几乎打破了椅子......

DateTime date = new DateTime(DateTime.Today.Year, 
                             DateTime.Today.Month, 
                             DateTime.Today.Day);
于 2009-10-07T05:33:38.633 回答
11

我经常偶然发现这种 var-abuse:

var ok = Bar();

甚至更好:

var i = AnyThing();

以这种方式使用 var 没有任何意义,也没有任何收获。它只是使代码更难遵循。

于 2009-10-07T06:31:27.970 回答
10
于 2009-10-07T05:32:21.753 回答
10

不理解 bool 是一种真正的类型,而不仅仅是一种约定

if (myBooleanVariable == true)
{
    ...
}

或者,甚至更好

if (myBooleanVariable != false)
{
    ...
}

像这样的结构经常被开发人员使用CC++其中布尔值的想法只是一个约定(0 == false,其他任何事情都是 true);在 C# 或其他具有真正布尔值的语言中,这不是必需的(或可取的)。

更新:改写最后一段以提高其清晰度。

于 2009-10-07T06:12:02.897 回答
9

类中的公共变量(使用属性代替)。

除非该类是一个简单的数据传输对象。

请参阅下面的评论以进行讨论和澄清。

于 2009-10-07T05:19:07.470 回答
8

我实际上已经看到了这一点。

bool isAvailable = CheckIfAvailable();
if (isAvailable.Equals(true))
{ 
   //Do Something
}

击败isAvailable == true反模式手!
使它成为一个超级反模式!

于 2009-10-09T12:55:25.993 回答
6

两个字符串反模式
Anti-Pattern #1
检查字符串是否为空或空

//Bad
if( myString == null || myString == "" )
OR
if( myString == null || myString.Length == 0 )

//Good
string.IsNullOrEmpty(myString)

Anti-Pattern #2(仅适用于 .NET 4.0)
检查字符串是否为空、空白或空白

//Bad
if( myString == null || myString == "" || myString.Trim() == "")

//Good
string.IsNullOrWhiteSpace(myString) 
于 2010-06-03T05:05:29.750 回答
6

私有自动实现的属性:

private Boolean MenuExtended { get; set; }
于 2009-10-07T05:32:06.543 回答
6

在每个方法的顶部声明和初始化所有局部变量真是太难看了!

void Foo()
{
    string message;
    int i, j, x, y;
    DateTime date;

    // Code
}
于 2009-10-07T06:26:33.347 回答
6
object variable;
variable.close(); //Old code, use IDisposable if available.
variable.Dispose(); //Same as close.  Avoid if possible use the using() { } pattern.
variable = null; //1. in release optimised away.  2. C# is GC so this doesn't do what was intended anyway.
于 2009-10-07T05:24:37.260 回答
5

不必要的转换(请相信编译器):

foreach (UserControl view in workspace.SmartParts)
{
  UserControl userControl = (UserControl)view;
  views.Add(userControl);
}
于 2009-10-07T05:33:40.987 回答
5
if(data != null)
{
  variable = data;
}
else
{
  variable = new Data();
}

可以更好地写为

variable = (data != null) ? data : new Data();

甚至更好地写成

variable = data ?? new Data();

最后的代码清单适用于 .NET 2.0 及更高版本

于 2009-10-09T12:52:30.957 回答
4

不使用三元是我看到转换为 c# 偶尔做的事情

你看:

private string foo = string.Empty;
if(someCondition)
  foo = "fapfapfap";
else
  foo = "squishsquishsquish";

代替:

private string foo  = someCondition ? "fapfapfap" : "squishsquishsquish";
于 2009-10-08T20:37:57.010 回答
4

说话带口音总是让我着迷。

C++ 程序员:

if (1 == variable) { }

在 C# 中,如果你要键入 ,这会给你一个编译器错误if (1 = variable),让你可以按照你的意思编写代码,而不用担心自己会伤到自己的脚。

于 2009-10-07T05:35:44.557 回答
3

访问修改后的闭包

foreach (string list in lists)
{
        Button btn = new Button();
        btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}

(请参阅链接以获取解释和修复)

于 2009-10-08T14:03:39.677 回答
3

用于使用字符串连接而不是字符串生成器连接任意数量的字符串

示例

foreach (string anItem in list)
    message = message + anItem;
于 2009-10-08T15:06:03.077 回答
2

这被认为是一般的吗?

public static main(string [] args)
{
  quit = false;
  do
  {
  try
  {
      // application runs here .. 
      quit = true;
  }catch { }
  }while(quit == false);
}

我不知道如何解释它,但这就像有人捕捉到异常并一遍又一遍地重试代码,希望它以后能工作。就像发生 IOException 一样,他们只是一遍又一遍地尝试直到它起作用。

于 2009-10-07T05:21:49.717 回答
2

我参与的项目有五十个类,都继承自同一个类,它们定义了:

public void FormatZipCode(String zipCode) { ... }

要么把它放在父类中,要么放在一边的实用程序类中。啊。

您是否考虑过浏览The Daily WTF

于 2009-10-08T14:21:23.790 回答
1

我以前有过这个:

AnEnum e = AnEnum.Abc;
int i = (int)e;
// lots of code
AnEnum f = (AnEnum)Enum.Parse(i, typeof(AnEnum));
于 2010-02-03T04:13:21.023 回答
1

在我继承的系统中发现了几次......

if(condition){
  some=code;
}
else
{
  //do nothing
}

反之亦然

if(condition){
  //do nothing
}
else
{
  some=code;
}
于 2009-10-08T20:47:40.593 回答
1
if (state == ((int)RowState.Active).ToString())
else if (state == ((int)RowState.NotActive).ToString())

state 是一个字符串 post 值,其中包含来自枚举 RowState 的值。

最终,这是我们用来检查价值的方式。

于 2010-02-03T18:52:13.437 回答
1

.NET 的主要问题似乎是有许多开发人员来自 VB 6.0 或(在我看来更糟,因为他们错误地认为他们知道该做什么,而 VB 6.0 程序员至少谦虚到愿意学习新东西)Java / C++。

人们对现代范式太无知了,人们用最糟糕的 C++ 风格的丑陋的 P/Invoke 涂抹他们的代码 - 可能的风格。:-(

于 2010-06-02T08:47:18.450 回答
1

非常复杂的“Page_Load”方法,它想要做所有事情。

于 2009-10-07T05:24:16.397 回答
1

将属性用于任何事情,而不是简单地检索一个值或可能的廉价计算。如果您从您的属性访问数据库,您应该将其更改为方法调用。开发人员预计方法调用可能代价高昂,他们不希望从属性中实现这一点。

于 2009-10-08T13:02:23.903 回答
0

无知是幸福(了解你的框架):

TimeSpan keyDays = new TimeSpan(Licence.LicenceExpiryDate.Ticks);
TimeSpan nowDays = new TimeSpan(System.DateTime.Now.Ticks);

int daysLeft = keyDays.Days - nowDays.Days;
于 2009-10-07T05:36:18.267 回答
0

使用(坏)

IEnumerable<Bar> foo = ...
if (foo.Count() > 0)
{
    ...
}

而不是(好)

IEnumerable<Bar> foo = ...
if (foo.Any())
{
    ...
}

测试 IEnumerable 是否包含任何内容。 Count()必须用 枚举整个集合MoveNext(),而Any()只需要调用MoveNext()一次。

于 2011-09-06T19:23:17.143 回答
0

我最近才看到一些。

永无止境的参数链

public string CreateJob(string siteNumber, string customer, string jobType, string description, string reference, string externalDoc, string enteredBy, DateTime enteredDateTime)
    {
        //recordtype = 0 for job
        //load assignments and phases set to false
        return Create(0, siteNumber, customer, jobType, description, reference, externalDoc, enteredBy, enteredDateTime, false, false);
    }

public string Create(int recordType, string siteNumber, string customer, string jobType, string description, string reference, string externalDoc, string enteredBy, DateTime enteredDateTime, bool loadAssignments, bool loadPhases)
{
    _vmdh.Fields.FieldByName("WDDOCTYPE").SetValue(recordType, false);
    _vmdh.Fields.FieldByName("NMDOCID").SetValue(-1, false);
    _vmdh.Init();           
        ....
        ...
        // And it keeps going
    }

想知道表格关闭时会发生什么

 private void frmAddImages_FormClosing(object sender, FormClosingEventArgs e)
{
    if (DialogResult != DialogResult.OK)
    {
        if (IsDirty)
        {
            e.Cancel = !(MessageBox.Show("Are you sure that you want to exit without saving", "Form Not Saved", MessageBoxButtons.YesNo) == DialogResult.Yes);
        }
    }
    }

字符串类型

switch (cbDateFilter.Text)
            {
                case "This Week":
                    dt = DateTime.Now;
                    while (dt.DayOfWeek != DayOfWeek.Monday) dt = dt.AddDays(-1); //find first day of week
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddDays(6).ToString("dd/MM/yyyy 23:59:59"));
                    break;

                case "This Month":
                    dt = DateTime.Now;
                    while (dt.Day != 1) dt = dt.AddDays(-1); // find first day of month
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddMonths(1).AddDays(-1).ToString("dd/MM/yyyy 23:59:59"));
                    break;

                case "This Quarter":
                    // if at end of Quarter then we need subtract -4 to get to priv Quarter
                    dt = DateTime.Now;
                    while (dt.Month != 7 &&
                        dt.Month != 10 &&
                        dt.Month != 1 &&
                        dt.Month != 4) dt = dt.AddMonths(-1); //find first month, fiscal year
                    while (dt.Day != 1) dt = dt.AddDays(-1); // find first day on month
                    dtFrom.Value = DateTime.Parse(dt.ToString("dd/MM/yyyy 00:00:00"));
                    dtTo.Value = DateTime.Parse(dt.AddMonths(3).AddDays(-1).ToString("dd/MM/yyyy 23:59:59"));
                    break;
于 2011-08-04T03:00:59.160 回答
0

在对属性进行编码时,只是自动给它一个 getter 和 setter,而不考虑它的用途。通常不使用 get 或 set,属性应该只读取 (get) 或只写入 (set)。

于 2011-03-10T11:48:31.807 回答
-2

过度使用/滥用对象初始化器,可能是因为懒惰:

var person = new Person
{
    FirstName = "joe",
    (... lots of setters down here)
};

没有意识到这几乎和公开所有领域一样糟糕。您应该始终注意创建一些有效的构造函数,将您的对象初始化为有效状态。

于 2009-10-07T06:03:52.213 回答