Интерфейсное ограничение для IComparable

Это было сложно выделить - ключ находится в источнике nuget, который содержит Selenium.WebDriver.ChromeDriver.targets - цели требуют явного присвоения свойств, поэтому chromedriver.exe никогда не копируется в каталог развертывания vstest.console , Вот исправление, которое нужно добавить в ваш файл CSPROJ:

Назначить PublishChromeDriver свойство в CSPROJ

  
    MyUX.Tests
     
    True
  

После того, как это свойство определено, копия chromedriver.exe будет скопирована в /bin для vstest.console. Это исправляет ошибку, которую мы получали:

chromedriver.exe file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at http://chromedriver.storage.googleapis.com/index.html

Альтернативный подход - принудительное копирование в CSPROJ

  
    
    
  

10
задан Joan Venge 27 May 2009 в 16:52
поделиться

5 ответов

Это два разных интерфейса. До .NET 2.0 не было дженериков, поэтому был только IComparable . В .NET 2.0 появились дженерики, и стало возможным сделать IComparable . Они делают то же самое. По сути, IComparable является устаревшим, хотя большинство библиотек распознают оба.

Чтобы сделать ваш код действительно совместимым, реализуйте оба, но сделайте один вызов другого, чтобы вам не пришлось писать один и тот же код дважды.

2
ответ дан 3 December 2019 в 22:38
поделиться

Основное различие между IComparable и IComparable <> заключается в том, что первый является предварительным обобщением, поэтому позволяет вызывать метод сравнения с любым объектом, тогда как второй обеспечивает, чтобы он имел тот же тип:

IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);

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


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

  • Если вы не ожидаете, что общий тип будет использовать какие-либо типы, которые только реализуют IComparable (т.е. устаревший код 1.0), и вы не вызываете никаких методы изнутри универсального, которые полагаются на параметр IComparable, затем используют только ограничение IComparable <>.

  • Если вы используете типы, которые реализуют только IComparable, тогда используйте только это ограничение

  • Если вы используете методы, требующие параметра IComparable, но не используете типы, которые реализуют только IComparable, тогда используйте оба ограничения как в Джеффе Ответ повысит производительность, если вы используете методы, которые принимают универсальный тип.

Чтобы расширить третье правило - предположим, что класс, который вы пишете, выглядит следующим образом:

public class StrangeExample<T> where ... //to be decided
{
    public void SortArray(T[] input)
    {
         Array.Sort(input);
    }

    public bool AreEqual(T a, T b)
    {
        return a.CompareTo(b) == 0;
    }
}

И нам нужно решить, какие ограничения наложить на Это. Метод SortArray вызывает Array.Sort, который требует, чтобы переданный массив содержал объекты, реализующие IComparable. Следовательно, мы должны иметь ограничение IComparable:

public class StrangeExample<T> where T : IComparable

Теперь класс будет компилироваться и работать правильно, поскольку массив T действителен для Array.Sort и в интерфейсе определен действительный метод .CompareTo. Однако, если вы уверены, что не захотите использовать свой класс с типом, который также не реализует интерфейс IComparable <>, вы можете расширить свое ограничение до:

public class StrangeExample<T> where T : IComparable, IComparable<T>

Это означает, что при вызове AreEqual он будет использовать более быстрый ,

5
ответ дан 3 December 2019 в 22:38
поделиться

Вам могут понадобиться оба ограничения, например:

where T : IComparable, IComparable<T>

Это сделает ваш тип совместимым с большим количеством пользователей. интерфейсов IComparable . Общая версия IComparable , IComparable поможет избежать упаковки, когда T является типом значения и позволяет более строго типизированные реализации методов интерфейса. . Поддержка обоих гарантирует, что независимо от того, какой интерфейс запрашивает другой объект, ваш объект может соответствовать требованиям и, следовательно, нормально взаимодействовать.

Например, Array.Sort и ArrayList.Sort используйте IComparable , а не IComparable .

5
ответ дан 3 December 2019 в 22:38
поделиться

IComparable позволяет компаратору быть строго типизированным .

Вы можете иметь

public int CompareTo(MyType other)
{
    // logic
}

вместо

public int CompareTo(object other)
{
    if (other is MyType)
        // logic
}

Возьмем, к примеру, следующий пример, который реализует оба интерфейса:

public class MyType : IComparable<MyType>, IComparable
{
    public MyType(string name, int id)
    { Name = name; Id = id; }

    public string Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(MyType other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        return (Id - other.Id > 0 ? 1 : 0);
    }

    public int CompareTo(object other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        if (other is MyType)
            return (Id - (other as MyType).Id > 0 ? 1 : 0);
        else
            throw new InvalidOperationException("Bad type");
    }
}


MyType t1 = new MyType("a", 1);
MyType t2 = new MyType("b", 2);
object someObj = new object();

// calls the strongly typed method: CompareTo(MyType other)
t1.CompareTo(t2);
// calls the *weakly* typed method: CompareTo(object other)
t1.CompareTo(someObj);

Если MyType был реализован только с IComparable , второй compareTo (someObj) будет ошибка времени компиляции. Это одно из преимуществ строго типизированных универсальных шаблонов .

С другой стороны, в структуре есть методы, требующие необщего IComparable , например Array.Sort ]. В этих случаях вам следует рассмотреть возможность реализации обоих интерфейсов, как в этом примере.

2
ответ дан 3 December 2019 в 22:38
поделиться

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

1
ответ дан 3 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: