Есть ли способ заставить существующий тип реализовать интерфейс? - PullRequest
3 голосов
/ 29 апреля 2009

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

public interface IKickAss
{
    int Yeahhhhhhh() { get; }
}

public static class Woot
{
    public int Bar(IKickAss a, IKickAss b)
    {
        return a.Yeahhhhhhh - b.Yeahhhhhhh;
    }
}

// What I'd like to do, sort of.
public partial struct Int32 : IKickAss
{
    public int Yeahhhhhhh
    {
        get
        {
            return this;
        }
    }
}

Я хотел этого много раз по многим причинам. Самым последним является то, что я реализовал радикальную сортировку для «uint», но также создал простой интерфейс «IRadixSortable», для которого требуется свойство «uint RadixKey {get}». Это означает, что я в основном продублировал код сортировки: один для массивов uint, другой для массивов IRadixSortable. Я предпочел бы просто написать один, заставив тип uint реализовать IRadixSortable. Есть ли способ сделать это ... может быть, с помощью отражения?

Haskell может сделать это (то есть классы типов могут быть созданы для любого типа данных в любое время), и я думаю, что это одна из очень важных причин, по которой он так мощен. C # действительно может использовать эту функцию. Может быть, это называется "интерфейс расширения":)

Ответы [ 6 ]

2 голосов
/ 29 апреля 2009

Не с интерфейсами, но вы можете сделать что-то подобное, используя методы расширения Вы просто не получили бы «контракт»

2 голосов
/ 29 апреля 2009

Да и нет.

Возможно, вы ищете Duck Typing , см. в следующей статье .

0 голосов
/ 29 апреля 2009

Я не вижу решения для встроенных типов, но для других типов (т. Е. Созданных вами или кем-то еще) вы можете просто создать подкласс и реализовать интерфейс по вашему выбору.

public interface ISortable
{
    // ... whatever you need to make a class sortable
}

public class ExistingType
{
    // whatever
}

public class NewType : ExistingType, ISortable
{
    // ...
}

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

0 голосов
/ 29 апреля 2009

Другие ответили на главный вопрос, но в отношении вашего конкретного сценария сортировки по основанию вы также можете взглянуть на тип шаблона, используемого в .NET Framework для сравнения, хеширования и т. Д .: разрешить пользователю вашего метода сортировки по основанию передать объект, который контролирует порядок сортировки. Например. создайте интерфейс IRadixKeyProvider (аналог IHashCodeProvider или IComparer) со свойством RadixKey.

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

0 голосов
/ 29 апреля 2009

Если вы управляете созданием экземпляров, вы можете наследовать от класса и реализовывать интерфейс в новом классе-наследнике.

0 голосов
/ 29 апреля 2009

А как насчет дженериков? Все базовые числовые типы реализуют ICopmarable, поэтому вы можете написать реализацию IComparer для передачи в метод Sort массива.

Или, возможно, метод расширения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...