Не может оператор == быть примененным к универсальным типам в C#?

Security Warning: этот ответ не соответствует лучшим рекомендациям по безопасности. Эвакуация неадекватна для предотвращения SQL-инъекции , вместо этого используйте подготовленные операторы . Используйте стратегию, изложенную ниже, на свой страх и риск. (Кроме того, mysql_real_escape_string() был удален в PHP 7.)

Вы могли бы сделать что-то основное:

$safe_variable = mysql_real_escape_string($_POST["user-input"]);
mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

Это не решит каждую проблему, но это очень хороший ступень. Я оставил очевидные элементы, такие как проверка существования переменной, числа (числа, буквы и т. Д.).

309
задан Hosam Aly 11 June 2018 в 05:01
поделиться

8 ответов

"... по умолчанию == ведет себя, как описано выше и для предопределенных и для пользовательских ссылочных типов. "

Тип T является не обязательно ссылочным типом, таким образом, компилятор не может сделать то предположение.

Однако это скомпилирует, потому что это более явно:

    bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }

Следуют до дополнительного вопроса, "Но, в случае, если я использую ссылочный тип, был бы == использование оператора предопределенное ссылочное сравнение, или это использовало бы перегруженную версию оператора, если бы тип определил тот?"

я думал бы, что == на Дженериках будет использовать перегруженную версию, но следующий тест демонстрирует иначе. Интересный... Я хотел бы знать почему! Если кто-то знает, совместно используйте.

namespace TestProject
{
 class Program
 {
    static void Main(string[] args)
    {
        Test a = new Test();
        Test b = new Test();

        Console.WriteLine("Inline:");
        bool x = a == b;
        Console.WriteLine("Generic:");
        Compare<Test>(a, b);

    }


    static bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }
 }

 class Test
 {
    public static bool operator ==(Test a, Test b)
    {
        Console.WriteLine("Overloaded == called");
        return a.Equals(b);
    }

    public static bool operator !=(Test a, Test b)
    {
        Console.WriteLine("Overloaded != called");
        return a.Equals(b);
    }
  }
}

Вывод

Встроенный: Перегруженный == названный

Универсальный:

Нажимают любую клавишу для продолжения...

Продолжают 2

, я действительно хочу указать что изменение мой сравнивать метод с [1 114]

    static bool Compare<T>(T x, T y) where T : Test
    {
        return x == y;
    }

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

139
ответ дан Enigma State 23 November 2019 в 01:14
поделиться

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

Вместо вызова Равняется, лучше использовать IComparer<T> - и если у Вас больше нет информации, EqualityComparer<T>.Default хороший выбор:

public bool Compare<T>(T x, T y)
{
    return EqualityComparer<T>.Default.Equals(x, y);
}

Кроме чего-либо еще, это старается не упаковывать/бросать.

281
ответ дан Jon Skeet 23 November 2019 в 01:14
поделиться

В целом, EqualityComparer<T>.Default.Equals должен сделать задание с чем-либо, что реализует IEquatable<T>, или это имеет разумное Equals реализация.

, Если, однако, == и Equals реализованы по-другому по некоторым причинам, то моя работа над универсальные операторы должна быть полезной; это поддерживает версии оператора (среди других):

  • Равный (T value1, T value2)
  • NotEqual (T value1, T value2)
  • GreaterThan (T value1, T value2)
  • LessThan (T value1, T value2)
  • GreaterThanOrEqual (T value1, T value2)
  • LessThanOrEqual (T value1, T value2)
40
ответ дан Marc Gravell 23 November 2019 в 01:14
поделиться

Компиляция не может знать, что T не мог быть структурой (тип значения). Таким образом, необходимо сказать ему, что это может только иметь ссылочный тип, я думаю:

bool Compare<T>(T x, T y) where T : class { return x == y; }

Это - потому что, если бы T мог бы быть типом значения, могли бы быть случаи, где x == y был бы плохо сформирован - в случаях, когда тип не имеет оператора == определенным. То же произойдет для этого, которое более очевидно:

void CallFoo<T>(T x) { x.foo(); }

, Который перестал работать также, потому что Вы могли передать тип T, который не будет иметь функционального нечто. C# вынуждает Вас удостовериться, что все возможные типы всегда имеют функциональное нечто. Это сделано где пункт.

12
ответ дан Johannes Schaub - litb 23 November 2019 в 01:14
поделиться

Кажется что без ограничения класса:

bool Compare<T> (T x, T y) where T: class
{
    return x == y;
}

нужно понять, что, в то время как class ограничил Equals в ==, оператор наследовался от Object.Equals, в то время как та из структуры переопределяет ValueType.Equals.

Примечание, что:

bool Compare<T> (T x, T y) where T: struct
{
    return x == y;
}

также выделяет ту же ошибку компилятора.

Пока еще я не понимаю, почему наличие сравнения оператора равенства типа значения отклоняется компилятором. Я действительно знаю для факта, хотя, что это работает:

bool Compare<T> (T x, T y)
{
    return x.Equals(y);
}
8
ответ дан Jon Limjap 23 November 2019 в 01:14
поделиться

Здесь есть запись MSDN Connect для этого

Ответ Алекса Тернера начинается с:

К сожалению, такое поведение дизайн и нет легкого решение, позволяющее использовать == с типом параметры, которые могут содержать значение типы.

4
ответ дан 23 November 2019 в 01:14
поделиться

bool Compare(T x, T y) where T : class { return x == y; }

Вышеупомянутое будет работать, потому что == заботится о в случае пользовательских ссылочных типов.
В случае типов значения, == может быть переопределен. В этом случае, "! =", должен также быть определен.

я думаю, что это могло быть причиной, она запрещает универсальное использование сравнения "==".

1
ответ дан shahkalpesh 23 November 2019 в 01:14
поделиться

.Equals() работы для меня, в то время как TKey универсальный тип.

public virtual TOutputDto GetOne(TKey id)
{
    var entity =
        _unitOfWork.BaseRepository
            .FindByCondition(x => 
                !x.IsDelete && 
                x.Id.Equals(id))
            .SingleOrDefault();


    // ...
}
0
ответ дан 23 November 2019 в 01:14
поделиться
Другие вопросы по тегам:

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