Были случаи, когда я хотел переопределить метод в классе с помощью метода расширения. Есть ли способ сделать это на C #?
Например:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Случай, когда я хотел это сделать, - это иметь возможность хранить хэш строки в базе данных и иметь то же значение, которое будет использоваться всеми классами, которые используют хэш класса строки (например, словарь и т. Д.). не гарантируется, что встроенный алгоритм хеширования .Net будет совместим от одной версии Framework к другой, я хочу заменить его своей собственной.
Есть другой случай, в котором я столкнулся, когда я хотел бы переопределить метод класса с помощью метода расширения, чтобы он не был специфичным только для строкового класса или метода GetHashCode.
Я знаю, что могу сделать это, создав подклассы существующего класса, но во многих случаях было бы удобно сделать это с помощью расширения.
источник
Ответы:
Нет; метод расширения никогда не имеет приоритета над методом экземпляра с подходящей сигнатурой и никогда не участвует в полиморфизме (
GetHashCode
являетсяvirtual
методом).источник
.ToString()
в массивах. Это определенно необходимая функция.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Если у метода другая подпись, то это можно сделать - так в вашем случае: нет.
Но в противном случае вам нужно использовать наследование, чтобы делать то, что вы ищете.
источник
Насколько я знаю, ответ отрицательный, потому что метод расширения не является экземпляром. Для меня это больше похоже на средство intellisense, которое позволяет вам вызывать статический метод с использованием экземпляра класса. Я думаю, что решением вашей проблемы может быть перехватчик, который перехватывает выполнение определенного метода (например, GetHashCode ()) и делает что-то еще. Чтобы использовать такой перехватчик (например, один Castle Project), все объекты должны быть созданы с помощью объектная фабрика (или контейнер IoC в Castle), чтобы их интерфейсы могли быть перехвачены через динамический прокси, созданный во время выполнения (Caslte также позволяет вам перехватывать виртуальные члены классов)
источник
Я нашел способ вызвать метод расширения с той же сигнатурой, что и метод класса, однако он не выглядит очень элегантным. Играя с методами расширения, я заметил недокументированное поведение. Образец кода:
Я заметил, что если бы я вызвал второй метод изнутри метода расширения, он вызвал бы метод расширения, соответствующий сигнатуре, даже если существовал метод класса, который также соответствовал бы сигнатуре. Например, в приведенном выше коде, когда я вызываю ExtFunc (), который, в свою очередь, вызывает ele.GetDesc (), я получаю строку возврата «Extension GetDesc» вместо ожидаемой строки «Base GetDesc».
Тестирование кода:
Это позволяет вам по желанию переключаться между методами класса и методами расширения, но требует добавления дублирующих «сквозных» методов, чтобы попасть в желаемую «область действия». Я называю это масштабом здесь из-за отсутствия лучшего слова. Надеюсь, кто-нибудь сможет сообщить мне, как это на самом деле называется.
По именам моих «сквозных» методов вы могли догадаться, что я также играл с идеей передачи им делегатов в надежде, что один или два метода могут действовать как сквозные для нескольких методов с одной и той же сигнатурой. К сожалению, этого не произошло, поскольку после распаковки делегата он всегда выбирал метод класса над методом расширения, даже изнутри другого метода расширения. «Размах» больше не имел значения. Я не очень часто использовал делегаты Action и Func, поэтому, возможно, кто-нибудь более опытный сможет разобраться в этой части.
источник