web-dev-qa-db-ja.com

オブジェクトのC#拡張メソッド

Objectクラスで拡張メソッドを使用することは良い考えですか?

このメソッドを登録することによって、コンテキストに読み込まれたすべてのオブジェクトに読み込まれるため、パフォーマンスが低下するかどうか疑問に思いました。

33
Mandrake

別の答えに加えて:

拡張メソッドはコンパイラの機能であるため、パフォーマンスの低下はありません。次のコードを検討してください。

public static class MyExtensions
{
    public static void MyMethod(this object) { ... }
} 

object obj = new object();
obj.MyMethod();

MyMethodの呼び出しは、実際には次のようにコンパイルされます。

MyExtensions.MyMethod(obj);
34
Andrew Bezzub

システム内のすべてのタイプにアタッチされるわけではないため、パフォーマンスが低下することはありません。システム内の任意のタイプで呼び出すことができるだけです。発生するのは、メソッドがインテリセンスのevery単一オブジェクトに表示されることだけです。

問題は次のとおりです。あなたは本当にオブジェクト上にある必要がありますか、それともより具体的にすることができますか。オブジェクト上にある必要がある場合は、オブジェクト用に作成します。

12
Darren Kopp

本当にすべてのオブジェクトを拡張するつもりなら、そうすることは正しいことです。ただし、拡張機能が実際にオブジェクトのサブセットにのみ適用される場合は、必要な最上位の階層レベルに適用する必要がありますが、それ以上は適用しないでください。

また、このメソッドは、ネームスペースがインポートされている場所でのみ使用できます。

指定した型にキャストしようとするメソッドのObjectを拡張しました。

public static T TryCast<T>(this object input)
{
    bool success;
    return TryCast<T>(input, out success);
}

また、successブール値を取り込むためにオーバーロードしました(TryParseと同様):

public static T TryCast<T>(this object input, out bool success)
{
    success = true;
    if(input is T)
        return (T)input;
    success = false;
    return default(T);
}

その後、これを拡張してinputの解析も試みました(ToStringを使用し、コンバーターを使用)。しかし、これはさらに複雑になります。

3
Mark Avenius

Objectクラスで拡張メソッドを使用することは良い考えですか?

はい、実際にそれが素晴らしいアイデアである場合があります。Objectクラスで拡張メソッドを使用しても、パフォーマンスが低下することはありません。このメソッドを呼び出さない限り、アプリケーションのパフォーマンスはまったく影響を受けません。

たとえば、特定のオブジェクトのすべてのプロパティをリストし、それをディクショナリに変換する次の拡張メソッドを考えます。

public static IDictionary<string, object> ObjectToDictionary(object instance)
{
    var dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    if (instance != null)
    {
        foreach (var descriptor in TypeDescriptor.GetProperties(instance))
        {
            object value = descriptor.GetValue(instance);
            dictionary.Add(descriptor.Name, value);
        }
    }
    return dictionary;
}
2
Darin Dimitrov

これは古い質問ですが、アクティブなオブジェクトの既存の検索機能を再利用しようとする回答はここにはありません。以下は、非アクティブなオブジェクトを見つけるためのオプションのオーバーロードを備えた簡潔な拡張メソッドです。

using System.Linq;

namespace UnityEngine {

public static class GameObjectExtensionMethods {

    public static GameObject Find(this GameObject gameObject, string name, 
        bool inactive = false) {

       if (inactive)
          return Resources.FindObjectsOfTypeAll<GameObject>().Where(
             a => a.name == name).FirstOrDefault();
       else
           return GameObject.Find(name);
    }
  }
}

Updateメソッド内でこの関数を使用する場合は、LINQステートメントをループトラバーサルの配列で変更して、ガベージの生成を排除することを検討してください。

0
Shaun

次の例は、使用中の拡張メソッドを示しています。

namespace NamespaceName
{
public static class CommonUtil
{
    public static string ListToString(this IList list)
    {
        StringBuilder result = new StringBuilder("");

        if (list.Count > 0)
        {
            result.Append(list[0].ToString());
            for (int i = 1; i < list.Count; i++)
                result.AppendFormat(", {0}", list[i].ToString());
        }
        return result.ToString();
    }
  }
}

次の例は、このメソッドの使用方法を示しています。

var _list = DataContextORM.ExecuteQuery<string>("Select name from products").ToList();
string result = _list.ListToString();
0
plywoods