Метод расширения, расширяющий T - плохая практика? - PullRequest
21 голосов
/ 15 апреля 2011

Я читал, что расширение System.Object обычно является плохой практикой, с чем я согласен.

Мне любопытно, однако, если следующий вариант будет считаться полезным методом расширения илиэто все еще плохая практика?

Это похоже на расширение System.Object, но не совсем,

    public static R InvokeFunc<T, R>(this T input, Func<T, R> func)
    {
        return func.Invoke(input);
    }

Это по существу позволяет любому объекту вызывать любую функцию, которая принимает этот объект в качестве параметра и возвращаетR, принадлежит ли эта функция к объекту или нет.Я думаю, что это может способствовать некоторой интересной «инверсии контроля», но не уверен в этом в целом.

Мысли?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2011

Ну, тут действительно два момента:

1) Хорошая ли идея создать метод расширения с this T, чтобы он применялся ко всем типам?

2) Полезен ли конкретный описанный метод расширения?

Для 1-го вопроса ответ иногда бывает, но зависит от контекста. Вы можете применить метод расширения ко всем классам так же, как это делает linq, гарантируя, что вы выберете подходящее пространство имен. Я думаю, что создание такого типа метода расширения в пространстве имен System - плохая идея, но если бы он был более целенаправленным, то, возможно, это было бы полезно.

Для 2-го, поскольку вызов является немедленным, тогда выбор синтаксиса следующий:

    int res = other.InvokeFunc<Other, int>(Callback);

    var res2 = (new Func<Other, int>(Callback))(other);

    var res3 = Callback(other);

Глядя на это, простой вызов метода, передающего экземпляр, является более естественным и типичным, однако, если ваш метод расширения становится более сложным, я возвращаюсь к своей первой мысли о том, что это зависит от контекста (который может помочь с инкапсуляцией).

1 голос
/ 15 апреля 2011

Все, что это делает, это то, что он дает вам возможность ссылаться на метод в качестве параметра, который фактически является тем, что делегат уже позволяет вам в C #.

Я не вижу, чтобы это было более полезно (в случае IoC), чем делегат типа Func<T,R> в вашем случае.Это просто еще один способ вызвать его.

ОБНОВЛЕНИЕ

Как уже упоминалось в комментариях, я думаю, что этот метод только помогает вам создавать делегатов более эффективно.Но в любом случае, вы больше не используете созданный делегат, поскольку вы вызываете его немедленно.Поэтому такой метод расширения будет иметь для меня больше смысла:

public static Func<R> InvokeFunc<T, R>(this T input, Func<T, R> func)
{
    return () => func(input);
}
...