Просматривая некоторый код, я заметил возможность изменить его, чтобы использовать дженерики. (Запутанный) код выглядит так:
public void DoAllTheThings(Type typeOfTarget, object[] possibleTargets)
{
var someProperty = typeOfTarget.GetProperty(possibleTargets[0]);
...
}
Этот код можно заменить на дженерики, например, так:
public void DoAllTheThings<T>(object[] possibleTargets[0])
{
var someProperty = type(T).getProperty(possibleTargets[0]);
...
}
Исследуя преимущества и недостатки этого подхода, я нашел термин, называемый общим злоупотреблением . Видеть:
- Защита непосвященного (разработчика) от генериков
- https://stackoverflow.com/questions/28203199/is-this-an-abuse-of-generics
- https://codereview.stackexchange.com/q/60695
Мой вопрос состоит из двух частей:
- Есть ли какая-то польза от перехода на такие дженерики? (Производительность? Читабельность?)
- Что такое родовое насилие? И использует ли generic каждый раз, когда есть параметр типа, злоупотребление ?
Ответы:
Когда дженерики применяются соответствующим образом, они удаляют код, а не просто перестраивают его. В первую очередь, код, который лучше всего удаляют дженерики, это типы типов, рефлексия и динамическая типизация. Таким образом, злоупотребление обобщенными типами может быть в общих чертах определено как создание универсального кода без значительного сокращения приведения типов, отражения или динамической типизации по сравнению с неуниверсальной реализацией.
Что касается вашего примера, я бы ожидал, что соответствующее использование обобщенных символов изменится на
object[]
aT[]
или аналогичное, а также будет избегатьType
илиtype
вообще. Это может потребовать значительного рефакторинга в другом месте, но если в этом случае уместно использовать непатентованные средства, в целом все должно быть проще, когда вы закончите.источник
object[]
наT[]
.Я бы использовал правило нонсенс: дженерики, как и все другие программные конструкции, существуют для решения проблемы . Если нет проблем с дженериками, их использование - это злоупотребление.
В конкретном случае универсальных шаблонов они в основном существуют для абстрагирования от конкретных типов, позволяя сворачивать реализации кода для различных типов в один универсальный шаблон (или как бы это ни назывался в вашем языке). Теперь предположим, что у вас есть код, который использует тип
Foo
. Вы можете заменить этот тип универсальнымT
, но если вам когда-либо нужен этот код для работыFoo
, просто нет другого кода, с которым вы можете сложить его вместе. Таким образом, не существует никакой проблемы, которая может быть решена, поэтому косвенное добавление универсального кода просто уменьшит читабельностьСледовательно, я бы предложил просто написать код без использования обобщений, пока не возникнет необходимость их введения (потому что вам нужно второе создание). Тогда и только тогда наступает время для рефакторинга кода для использования обобщений. Любое использование до этого момента является злоупотреблением в моих глазах.
Кажется, это звучит слишком педантично, поэтому позвольте мне напомнить вам:
в программировании нет правил без исключений. Это правило включено.
источник
Код выглядит странно. Но если мы вызываем его, выглядит лучше указать тип как универсальный.
https://stackoverflow.com/questions/10955579/passing-just-a-type-as-a-parameter-in-c-sharp
Лично мне не нравятся эти искажения, которые делают вызывающий код красивым. например, вся «беглая» вещь и методы расширения.
Но вы должны признать, что у него есть популярный последователь. даже Microsoft использует его в единстве, например
источник
Мне кажется, ты был на правильном пути, но не закончил работу.
Рассматривали ли вы изменение
object[]
параметраFunc<T,object>[]
на следующий шаг?источник