C # Можно ли создать необязательные ограничения общего типа - PullRequest
7 голосов
/ 15 июля 2011

Я думаю, что знаю ответ на этот вопрос, но мне нужно указать, что универсальный метод может принимать тип на основе двух необязательных ограничений.В связи с тем, что T может быть либо одного типа, либо другого.

public WebPage Click<T>(Func<WebPage> predicate) where T : LinkBase || FieldBase, new()
{
    WebDriver.FindElement(new T().LinkPath).Click();
    WebDriver.Wait();
    return predicate.Invoke();
}

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

Ответы [ 3 ]

6 голосов
/ 15 июля 2011

Делать это не имеет смысла, если LinkBase и FieldBase не имеют общей базы или не реализуют общий интерфейс. И если они это сделают, то вы можете просто использовать это как ограничение.

Я говорю, что это не имеет смысла, потому что сама причина использования ограничений типа состоит в том, чтобы удостовериться, что фактический используемый параметр универсального типа поддерживает известный общедоступный интерфейс (в противном случае вы могли бы просто сделать все это не - универсальный и использовать object). Но если у вас есть гипотетическое ограничение «или», как компилятор сможет убедиться, что код, который вы пишете внутри универсального шаблона, действительно будет иметь значение для параметра типа, который в итоге будет указан?

3 голосов
/ 15 июля 2011

Вы правы, нет способа передать несколько типов в общий метод.

У вас есть контроль над обоими типами? Можете ли вы заставить их реализовать один и тот же интерфейс или абстрактный класс?

2 голосов
/ 15 июля 2011

Одним из вариантов решения таких проблем является применение шаблона адаптера к вашим классам. В этом случае они имеют одинаковые свойства, но не одинаковый интерфейс. (Это наиболее полезно, если вы не управляете источником или для них не имеет смысла фактически использовать интерфейс в обычных сценариях.)

interface ILinkablePath
{
    string LinkPath { get; }
}

class LinkBaseAdapter : ILinkablePath 
{
    private LinkBase linkBase;

    public LinkBaseAdapter(LinkBase linkBase) 
    {
        this.linkBase = linkBase;
    }

    public string LinkPath { get { return this.linkBase.LinkPath; } }
}

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

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

В противном случае для вашей конкретной проблемы вы можете просто создать различные методы для каждого типа, который вы хотите поддерживать, или (если вы работаете только с одним свойством, а не с остальным объектом), просто передайте значение свойства, которое вы хотите использовать, а не сам объект.

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