Переопределение методов класса String

174
19 октября 2017, 07:51
static class MyString : String
{
    static public string[] Split(this string s)
    {
        return Split(s, @"\t");
    }
    static public string[] Split(this string s, string d)
    {
        return Regex.Split(s, d);
    }
}

У переменной типа string есть методы. Как я понял эти методы принадлежат классу String. В идеале мне нужно переопределить метод Split не в моем классе, а в классе String, но у меня это не получилось (мало опыта).

Два вопроса:

  1. Возможно ли переопределение в классе String, чтобы...

    string a; a.Split();

...у переменной a метод Split вызывался мой?

  1. Как возможно реализовать мой вариант с моим методом? Выдает ошибку:

CS0713 Статический класс "MyString" не может быть производным от типа "string". Статические классы должны быть производными от object.

Answer 1

1.Возможно ли переопределение в классе String, чтобы...

Нет. Метод-расширение не может переопределить метод, объявленный в классе.

Если в классе уже есть метод с такой же сигнатурой, то он всегда будет иметь приоритет над методом-расширением.

В Вашем случае сигнатура первого метода совпадает с уже существующим методом String.Split(params char[]). Соответственно, при вызове:

var result = a.Split();

вызовется стандартный метод с пустым массивом разделителей. Согласно документации строка в данном случае делится по любым пробельным символам, а не только по табуляции:

... If the separator argument is null or contains no characters, the method treats white-space characters as the delimiters. White-space characters are defined by the Unicode standard; they return true if they are passed to the Char.IsWhiteSpace method.

Вы все еще сможете вызвать свой метод, обратившись к нему напрямую:

MyString.Split(a);

Но, чтобы использовать его как расширение Вам придется дать ему другое имя. Советую дать осмысленное название, связанное с тем, что делает метод, например SplitByTab.

Второй метод по сигнатуре не совпадает с существующими, но для удобочитаемости кода лучше дать ему более говорящее название, отличное от стандартного Split.

Как возможно реализовать мой вариант с моим методом? Выдает ошибку:

Для того-чтобы объявить методы-расширения не нужно наследоваться от класса. Уберите наследование от String:

static class MyStringExtensions
{
    static public string[] SplitByTab(this string s)
    {
        return SplitByRegex(s, @"\t");
    }
    static public string[] SplitByRegex(this string s, string pattern)
    {
        return Regex.Split(s, pattern);
    }
}
Answer 2
  1. Вы не можете наследоваться от класса System.String, так как он является sealed
  2. Вы можете добавить свои методы для string с помощью extension-a:

    public static class MyStringExtensions
    {
        public static string[] MySplit(this string s)
        {
            return s.Split('\t');
        }
        public static string[] MySplit(this string s, string d)
        {
            return Regex.Split(s, d);
        }
    }
  3. Вы не можете переопределить уже имеющиеся методы в string. Даже с помощью extension-а, так как в этом случае вызываться будет метод из самого класса, а не из extension-a

Answer 3

Используйте методы расширения и определяйте свой собственный метод. Вот пример с консольным приложением:

namespace ConsoleApp1
{
 class Program
 {
    static void Main(string[] args)
    {
        string ST = "teststring";
        ST.MySplit();
    } 
}
static class ext
{
    public static string MySplit(this string str)
    {
        return str + "!!!";
    }
}

}

READ ALSO
Аггрегирование в сервис-контракте WCF

Аггрегирование в сервис-контракте WCF

Можно ли как-то в сервис-контакте WCF, в интерфейсе, описать не методы, а аггрегированные объекты, в которых уже находятся нужные мне методы?...

186
Вывод из базы данных в RoR

Вывод из базы данных в RoR

Я новичок, и мне нужен Ваш совет

254
Чтение файла с ошибкой nodejs

Чтение файла с ошибкой nodejs

У меня в expressjs есть router

302