17

メソッドを使用して C# のオブジェクトと対話するさまざまな方法、特に次の主な設計上の違いと結果について少し混乱しています。

  1. インスタンスメソッドの呼び出し
  2. POCO で静的クラスを使用する
  3. 拡張メソッドの作成

例:

public class MyPoint
{
    public double x { get; set; }
    public double y { get; set; }

    public double? DistanceFrom(MyPoint p)
    {
        if (p != null)
        {
            return  Math.Sqrt(Math.Pow(this.x - p.x, 2) + Math.Pow(this.y - p.y, 2));
        }
        return null;
    }
}

メソッドをクラス定義に配置するだけで目的の結果を達成できるのであれば、静的ヘルパー クラスまたは拡張メソッドと組み合わせた POCO が望ましいのはなぜでしょうか?

4

4 に答える 4

20

「メソッドをクラス定義に配置するだけで目的の結果を達成できるのであれば、静的ヘルパー クラスまたは拡張メソッドと組み合わせた POCO が望ましいのはなぜですか?」

答えは、状況に依存し、問題のメソッドがクラスの主な関心事に直接関連するかどうかです (単一責任の原則を参照)。

以下に、各タイプのアプローチ/方法を使用することが適切な例をいくつか示します (コード サンプルを出発点として使用します)。

1. インスタンスメソッド

//This all makes sense as instance methods because you're 
//encapsulating logic MyPoint is concerned with.
public class MyPoint
{
    public double x { get; set; }
    public double y { get; set; }

    public double? DistanceFrom(MyPoint p)
    {
        if (p != null)
            return  Math.Sqrt(Math.Pow(this.x - p.x, 2) + Math.Pow(this.y - p.y, 2));            
        return null;
    }
}

2. 静的クラス メソッド- エラー ログの例。

    //Your class doesn't directly concern itself with logging implmentation;
    //that's something that is better left to a separate class, perhaps
    //a "Logger" utility class with static methods that are available to your class.
    public double? DistanceFrom(MyPoint p)
    {
        try
        {
            if (p != null)
                return  Math.Sqrt(Math.Pow(this.x - p.x, 2) + Math.Pow(this.y - p.y, 2));            
            return null;
        }
        catch(Exception ex)
        {
             //**** Static helper class that can be called from other classes ****
             Logger.LogError(ex);

             //NOTE: Logger might encapsulate other logging methods like...
             //Logger.LogInformation(string s)
             //...so an extension method would be less natural, since Logger
             //doesn't relate to a specific base type that you can create an
             //extension method for.
        }
}

3. 拡張メソッド- XML シリアル化の例。

//Maybe you want to make it so that any object can XML serialize itself
//using an easy-to-use, shared syntax.
//Your MyPoint class isn't directly concerned about XML serialization,
//so it doesn't make sense to implement this as an instance method but
//MyPoint can pick up this capability from this extension method.
public static class XmlSerialization
{
    public static string ToXml(this object valueToSerialize)
    {
        var serializer = new XmlSerializer(valueToSerialize.GetType());
        var sb = new StringBuilder();
        using (var writer = new StringWriter(sb))
            serializer.Serialize(writer, valueToSerialize);

        return sb.ToString();
    }
}

//example usage
var point = new MyPoint();
var pointXml = point.ToXml(); //<- from the extension method

経験則は次のとおりです。

  1. メソッドがクラスの主な関心事に関連する場合は、インスタンス メソッドに入れます。
  2. 複数のクラスに役立つ汎用ユーティリティがある場合は、それを静的クラスのメソッドに配置することを検討してください。
  3. 2 に似ているが単一の基本型に関連する状況がある場合、または静的クラスを個別に参照しなくてもコードがよりクリーン/簡潔に見えると思われる場合は、拡張メソッドを検討してください。
于 2015-05-29T18:52:19.863 に答える