簡単に言えば、 Javaアンチパターン は不可欠なリソースです。初心者から専門家まで。 C#でこのようなものをまだ見つけていません。そこで、この質問をコミュニティWikiとして公開し、全員にこのことに関する知識を共有してもらいます。私はC#が初めてなので、これに非常に興味がありますが、いくつかのアンチパターンから始めることはできません:/
以下は、他の言語ではなくC#に特に当てはまる答えです。
これらをコピー/ペーストしただけです!これらについてのコメントも見てみてください。
NullReferenceException
を投げる間違った例外を投げる:
_if (FooLicenceKeyHolder == null)
throw new NullReferenceException();
_
クラス内のパブリック変数(代わりにプロパティを使用します)。
Unlessクラスは単純なデータ転送オブジェクトです。
_if (myBooleanVariable == true)
{
...
}
_
または、さらに良い
_if (myBooleanVariable != false)
{
...
}
_
このような構造は、ブール値の概念が単なる慣習であるC
および_C++
_開発者によってよく使用されます(0 == false、その他はすべて真)。これは、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.
_
例外を誤って再スローします。例外を再スローするには:
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
}
ガベージコレクターを信頼する代わりに収集するGC.Collect()
。
JavaとC#...
if(something == true){
somethingelse = true;
}
ボーナスポイントも持っている場合
else{
somethingelse = false;
}
using Microsoft.SharePoint;
'言っ途切れる
私は次のコードをたくさん見ます:
if (i==3)
return true;
else
return false;
する必要があります:
return (i==3);
デメテルの法則をIn辱する:
a.PropertyA.PropertyC.PropertyB.PropertyE.PropertyA =
b.PropertyC.PropertyE.PropertyA;
NullReferenceException
を投げる:
if (FooLicenceKeyHolder == null)
throw new NullReferenceException();
これは本当です、私は自分の目で見ました。
public object GetNull()
{
return null;
}
それは実際にアプリで使用され、さらにそれと一緒に行くためのストアドプロシージャ、nullを返すsp_GetNullさえも持っていました。
それは私の一日を作りました。
私はspが古典的なASPサイトに使用されたと思います..結果セットと関係があります。 .netのものは、コードを.netに「変換」する誰かのアイデアでした...
int foo = 100;
int bar = int.Parse(foo.ToString());
または、より一般的な場合:
object foo = 100;
int bar = int.Parse(foo.ToString());
私たちのプロジェクトでこれを見つけて、椅子をほとんど壊しました...
DateTime date = new DateTime(DateTime.Today.Year,
DateTime.Today.Month,
DateTime.Today.Day);
私はこの種のvar-abuseにつまずくことがよくあります。
var ok = Bar();
またはさらに良い:
var i = AnyThing();
Varをそのように使用しても意味がなく、何も得られません。コードを追跡するのが難しくなります。
Boolは単なる慣習ではなく実際の型であることを理解していない
if (myBooleanVariable == true)
{
...
}
または、さらに良い
if (myBooleanVariable != false)
{
...
}
これらのような構造は、ブール値の概念が単なる慣習であるC
およびC++
開発者によってよく使用されます(0 == false、その他はすべて真)。これは、C#または真のブール値を持つ他の言語では必要ありません(または望ましくありません)。
更新:わかりやすくするために最後の段落を言い換えました。
クラス内のパブリック変数(代わりにプロパティを使用します)。
nlessクラスは単純なデータ転送オブジェクトです。
議論と説明については、以下のコメントを参照してください。
私は実際にこれを見ました。
bool isAvailable = CheckIfAvailable();
if (isAvailable.Equals(true))
{
//Do Something
}
isAvailable == true
アンチパターンの伝承!
これを超アンチパターンにします!
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.
プライベート自動実装プロパティ:
private Boolean MenuExtended { get; set; }
2つのストリングアンチパターン
アンチパターン#1
nullまたは空の文字列をチェック
//Bad
if( myString == null || myString == "" )
OR
if( myString == null || myString.Length == 0 )
//Good
string.IsNullOrEmpty(myString)
Anti-Pattern#2(.NET 4.0のみ)
null、空、または空白の文字列の確認
//Bad
if( myString == null || myString == "" || myString.Trim() == "")
//Good
string.IsNullOrWhiteSpace(myString)
各メソッドの上部ですべてのローカル変数を宣言して初期化するのは非常に面倒です!
void Foo()
{
string message;
int i, j, x, y;
DateTime date;
// Code
}
不必要なキャスト(コンパイラを信頼してください):
foreach (UserControl view in workspace.SmartParts)
{
UserControl userControl = (UserControl)view;
views.Add(userControl);
}
if(data != null)
{
variable = data;
}
else
{
variable = new Data();
}
次のように書くことができます
variable = (data != null) ? data : new Data();
さらに良いように書かれて
variable = data ?? new Data();
最後のコードリストは.NET 2.0以降で機能します
アクセントで話すことは常に私をキャッチしました。
C++プログラマー:
_if (1 == variable) { }
_
C#では、if (1 = variable)
と入力するとコンパイラエラーが発生し、足を踏み入れることを心配する代わりに、意図したとおりにコードを記述できます。
ターナリーを使用しないことは、時々c#に変換されることがあります
分かりますか:
private string foo = string.Empty;
if(someCondition)
foo = "fapfapfap";
else
foo = "squishsquishsquish";
の代わりに:
private string foo = someCondition ? "fapfapfap" : "squishsquishsquish";
Stringbuilderの代わりに文字列連結を使用して任意の数の文字列を連結する場合
例
foreach (string anItem in list)
message = message + anItem;
foreach (string list in lists)
{
Button btn = new Button();
btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}
(説明と修正についてはリンクを参照してください)
これは一般的と見なされますか?
public static main(string [] args)
{
quit = false;
do
{
try
{
// application runs here ..
quit = true;
}catch { }
}while(quit == false);
}
私はそれを説明する方法を知りませんが、誰かが例外をキャッチし、後で動作することを何度も何度も再試行するようなものです。 IOExceptionが発生した場合と同様に、動作するまで何度も試行します。
私が取り組んでいるプロジェクトには、同じクラスから継承する50のクラスがあり、allが定義されています:
public void FormatZipCode(String zipCode) { ... }
親クラスに入れるか、ユーティリティクラスを脇に置きます。ああ。
The Daily WTF の閲覧を検討しましたか?
私が継承したシステムでこれを数回見つけました...
if(condition){
some=code;
}
else
{
//do nothing
}
およびその逆
if(condition){
//do nothing
}
else
{
some=code;
}
非常に複雑な「Page_Load」メソッド。すべてを実行したい。
私はこれを前に持っていました:
AnEnum e = AnEnum.Abc;
int i = (int)e;
// lots of code
AnEnum f = (AnEnum)Enum.Parse(i, typeof(AnEnum));
if (state == ((int)RowState.Active).ToString()) else if (state == ((int)RowState.NotActive).ToString())
stateは、列挙RowStateからの値を含む文字列ポスト値です。
最終的に、これは値に対してチェックするために使用する方法です。
単に値を取得するためだけでなく、場合によっては安価な計算以外の目的でプロパティを使用する。プロパティからデータベースにアクセスしている場合は、メソッド呼び出しに変更する必要があります。開発者は、メソッド呼び出しにコストがかかる可能性があることを期待していますが、プロパティからこれを期待していません。
.NETの主な問題は、VB 6.0または(さらに悪いことには、VB 6.0プログラマーは、少なくとも新しいことを学ぼうとするほど謙虚です)Java/C++。
現代のパラダイムに対して無知すぎる人々、可能な限り最悪のC++スタイルでcodeいP/Invokeでコードを塗りつぶしている人々。 :-(
無知は至福です(フレームワークを知ってください):
TimeSpan keyDays = new TimeSpan(Licence.LicenceExpiryDate.Ticks);
TimeSpan nowDays = new TimeSpan(System.DateTime.Now.Ticks);
int daysLeft = keyDays.Days - nowDays.Days;
使用(悪い)
_IEnumerable<Bar> foo = ...
if (foo.Count() > 0)
{
...
}
_
代わりに(良い)
_IEnumerable<Bar> foo = ...
if (foo.Any())
{
...
}
_
iEnumerableに何かが含まれているかどうかをテストする。 Count()
はMoveNext()
を使用してコレクション全体を列挙する必要がありますが、Any()
はMoveNext()
を1回呼び出すだけです。
私は最近いくつかを見ました。
終了しないパラメータチェーン
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;
プロパティをコーディングするときは、その使用を考えずにゲッターとセッターを自動的に与えるだけです。多くの場合、getまたはsetは使用されず、プロパティは読み取り(get)のみ、または書き込み(set)のみにする必要があります。