Почему статическое виртуальное невозможно? Является ли C# зависимым или просто не имеет смысла в мире OO?C# виртуальный статический метод
Я знаю, что концепция уже подчеркнута, но я не нашел простого ответа на предыдущий вопрос.
Почему статическое виртуальное невозможно? Является ли C# зависимым или просто не имеет смысла в мире OO?C# виртуальный статический метод
Я знаю, что концепция уже подчеркнута, но я не нашел простого ответа на предыдущий вопрос.
virtual
означает, что указанный метод будет выбран во время выполнения, в зависимости от динамического типа объекта. static
означает, что для вызова метода не требуется объект.
Как вы предлагаете делать оба в том же методе?
мы не называем их функциями :) мы называем их методами –
@ Yassir : Ах, спасибо. Прогулка со мной, как с парнем C++. :) Я исправлю это. – sbi
я wouldlike сделать что-то вроде этого:. ((I) TypeOf (mybject)) MyStaticFunction (с I, интерфейс с MyStaticFunction статической функцией интерфейса) Я знаю синтаксис неверен, но вот точка. – Toto
В .NET диспетчер виртуальных методов (грубо) выполняется путем просмотра фактического типа объекта при вызове метода во время выполнения и нахождения наиболее переопределяющего метода из таблицы vtable класса. При вызове статического класса нет экземпляра объекта для проверки, и поэтому нет vtable для поиска.
Эрик Липперт имеет в блоге об этом, и, как обычно, с его должности, он охватывает предмет в большой глубине:
«виртуальный» и «статические» противоположны! «Virtual» означает «определить метод, который будет вызываться на основе информации о типе времени выполнения», а «статический» означает «определить метод, который будет называться только на основе статического анализа времени компиляции».
Хотя технически это невозможно чтобы определить статический виртуальный метод, по всем причинам, уже указанным здесь, вы можете функционально выполнить то, что, как я думаю, пытается использовать методы расширения C#.
Из MSDN:
Методы расширения позволяют «добавлять» методы к существующим типам без создания нового производного типа, перекомпиляции или иным образом модифицировать исходного типа.
Для получения более подробной информации ознакомьтесь с C# Extension Methods (C# Programming Guide).
Методы расширения не отличаются от простых виртуальных. –
Я собираюсь быть тем, кто naysays. То, что вы описываете, технически не является частью языка. Сожалею. Но возможно имитировать его в пределах языка.
Давайте рассмотрим, о чем вы просите, - вам нужна коллекция методов, которые не привязаны к какому-либо конкретному объекту, который может быть легко вызван и заменен во время выполнения или времени компиляции.
Для меня это похоже на то, что вы действительно хотите - это одноэлементный объект с делегированными методами.
Давайте соберем вместе пример:
public interface ICurrencyWriter {
string Write(int i);
string Write(float f);
}
public class DelegatedCurrencyWriter : ICurrencyWriter {
public DelegatedCurrencyWriter()
{
IntWriter = i => i.ToString();
FloatWriter = f => f.ToString();
}
public string Write(int i) { return IntWriter(i); }
public string Write(float f) { return FloatWriter(f); }
public Func<int, string> IntWriter { get; set; }
public Func<float, string> FloatWriter { get; set; }
}
public class SingletonCurrencyWriter {
public static DelegatedCurrencyWriter Writer {
get {
if (_writer == null)
_writer = new DelegatedCurrencyWriter();
return _writer;
}
}
}
в использовании:
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400.0
SingletonCurrencyWriter.Writer.FloatWriter = f => String.Format("{0} bucks and {1} little pennies.", (int)f, (int)(f * 100));
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400 bucks and 0 little pennies
Учитывая все это, мы теперь имеем класс одноплодной, который выписывает валютные ценности, и я могу изменить поведение его ,Я в основном определил поведение конвенции во время компиляции и теперь могу изменить поведение либо во время компиляции (в конструкторе), либо во время выполнения, что, я считаю, эффект, который вы пытаетесь получить. Если вы хотите наследовать поведение, вы можете сделать это путем реализации обратной цепочки (т. Е. Новый метод вызывает предыдущий).
Тем не менее, я не особо рекомендую приведенный выше пример кода. Во-первых, он не является потокобезопасным, и на самом деле не так много, чтобы поддерживать жизнь. Глобальная зависимость от такого типа структуры означает глобальную нестабильность. Это один из многих способов, с помощью которых изменяемое поведение было реализовано в темные дни C: structs указателей функций, и в этом случае одна глобальная структура.
Противоречие между «статическим» и «виртуальным» является только проблемой C#. Если бы «статические» были заменены на «уровень класса», как и на многих других языках, никто не был бы с завязанными глазами.
Слишком плохой выбор слов, сделанных C# калекой в этом отношении. По-прежнему можно вызвать метод Type.InvokeMember для имитации вызова уровня класса, виртуального метода. Вам просто нужно передать имя метода как строку. Отсутствие проверки времени компиляции, отсутствие сильного ввода и отсутствие контроля над тем, что подклассы реализуют этот метод.
Некоторые Delphi красоты:
type
TFormClass = class of TForm;
var
formClass: TFormClass;
myForm: TForm;
begin
...
formClass = GetAnyFormClassYouWouldLike;
myForm = formClass.Create(nil);
myForm.Show;
end
Это не «плохой выбор слов», определение «статический» - * «определяет метод, который будет называться только на основе статического анализа времени компиляции» * в соответствии с ответом Майкла Стама (http: // stackoverflow.com/a/1244431/648265) - это то, что на самом деле означало с момента его введения в C. Запрос функции эффективно меняет свой смысл на «class-bound». –
Ребята, которые говорят, что нет никакого смысла в статических виртуальных методов. Если вы не понимаете, как это возможно, это не означает, что это невозможно. Есть языки, которые позволяют это! Посмотрите, например, на Delphi.
Да, это возможно.
Наиболее хотел использовать случай для того, чтобы иметь заводов, которые могут быть «переопределенными»
Для того, чтобы сделать это, вам придется полагаться на параметрах универсального типа с использованием F-bounded polymorphism.
Пример 1 Давайте возьмем пример фабрики:
class A: { public static A Create(int number) { return ... ;} }
class B: A { /* How to override the static Create method to return B? */}
Вы также хотите createB
быть доступными и возвращать объекты B в классе B. Или вы могли бы статические функции А, чтобы быть библиотека, которая должна быть расширяемой B. Решение:
class A<T> where T: A<T> { public static T Create(int number) { return ...; } }
class B: A<B> { /* no create function */ }
B theb = B.Create(2); // Perfectly fine.
A thea = A.Create(0); // Here as well
Пример 2 (продвинутый): Определим статическую функцию для умножения матриц значений.
public abstract class Value<T> where T : Value<T> {
//This method is static but by subclassing T we can use virtual methods.
public static Matrix<T> MultiplyMatrix(Matrix<T> m1, Matrix<T> m2) {
return // Code to multiply two matrices using add and multiply;
}
public abstract T multiply(T other);
public abstract T add(T other);
public abstract T opposed();
public T minus(T other) {
return this.add(other.opposed());
}
}
// Abstract override
public abstract class Number<T> : Value<T> where T: Number<T> {
protected double real;
/// Note: The use of MultiplyMatrix returns a Matrix of Number here.
public Matrix<T> timesVector(List<T> vector) {
return MultiplyMatrix(new Matrix<T>() {this as T}, new Matrix<T>(vector));
}
}
public class ComplexNumber : Number<ComplexNumber> {
protected double imag;
/// Note: The use of MultiplyMatrix returns a Matrix of ComplexNumber here.
}
Теперь вы можете также использовать статический MultiplyMatrix
метод возвращает матрицу комплексных чисел непосредственно из ComplexNumber
Matrix<ComplexNumber> result = ComplexNumber.MultiplyMatrix(matrix1, matrix2);
На самом деле это называется «[Любопытно повторяющийся шаблон шаблона] (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)». –
Это имя было изобретен инженером в 1995 году минимум через 6 лет после того, как F-ограниченный полиморфизм был математически формализован. http://bit.ly/1Ft54Ah В то время не было Интернета, хотя я не могу обвинять его в том, что он не смотрел на него (Google был основан в 1999 году) –
Вау, я этого не знал. Добавлено это в статью Википедии. –
Суммируя все варианты представлены:
Это не часть C#, потому что в нем static
means "not bound to anything at runtime", как это было с C (и, возможно, раньше).static
Объекты - это, связанные с типом объявления (таким образом, они могут обращаться к другим объектам static
), но только во время компиляции.
static
equivalent (if needed at all) means "bound to a type object at runtime". Примеры включают Delphi, Python, PHP.Это можно эмулировать в ряде способов, которые могут быть классифицированы как:
Может вы разделили свой второй q вопрос в отдельный вопрос? – EFraim
Разбивается на следующую тему: вызов статического метода интерфейса C# с генериками – Toto
Дубликат: http://stackoverflow.com/questions/248263/why-cant-i-declare-c-methods-virtual-and-static –