Ваш тест фильтра -
var result = data.filter((value, i, arr) => {
return value[0] !== arr[i][0]
});
Но arr[i]
всегда будет ссылаться на текущий элемент, перебираемый через - value
, поэтому, независимо от ввода, value[0] !== arr[i][0]
всегда будет оценивать как [ 115]. (потому что value === arr[i]
, так value[0] === arr[i][0]
).
Вы можете добавить value[0]
к Set
, и при тестировании проверить, существует ли это значение в наборе или нет:
var data = [
['dupeValue', { data: 123 }],
['dupeValue', { data: 123 }],
['otherValue', { data: 1111111 }],
['dupeValue', { data: 123 }]
]
const firstElements = new Set();
var result = data.filter(([firstElement]) => {
const alreadyHas = firstElements.has(firstElement);
firstElements.add(firstElement);
return !alreadyHas;
})
console.log(result)
Вы не можете действительно "препятствовать тому", чтобы IDisposable распространился. Некоторые классы должны быть расположены, как AutoResetEvent
, и самый эффективный путь состоит в том, чтобы выполнить в нем Dispose()
метод для предотвращения издержек финализаторов. Но этот метод нужно назвать так или иначе, так же точно как в Вашем примере классы, которые инкапсулируют или содержат IDisposable, должны расположить их, таким образом, они должны быть доступными также и т.д. Единственный способ избежать его к:
using
шаблон)В некоторых случаях IDisposable может быть проигнорирован, потому что он поддерживает дополнительный случай. Например, WaitHandle реализует IDisposable для поддержки именованного Взаимного исключения. Если имя не используется, Расположить метод ничего не делает. MemoryStream является другим примером, он не использует системных ресурсов, и Располагать реализацию также ничего не делает. Тщательные взгляды о том, используется ли неуправляемый ресурс или не может быть учебным. Так может исследование доступных источников для библиотек .NET или использование декомпилятора.
С точки зрения правильности Вы не можете предотвратить распространение IDisposable через объектные отношения, если родительский объект создает и по существу владеет дочерним объектом, который должен теперь быть доступным. FxCop корректен в этой ситуации, и родитель должен быть IDisposable.
То, что можно сделать, стараются не добавлять IDisposable к листовому классу в иерархии объектов. Это - не всегда легкая задача, но это - интересное осуществление. С логической точки зрения нет никакой причины, что ShoeLace должен быть доступным. Вместо того, чтобы добавить WaitHandle здесь, это также возможный добавить ассоциацию между ShoeLace и WaitHandle в точке, это используется. Самый простой путь через экземпляр Словаря.
Если можно переместить WaitHandle в свободную ассоциацию с помощью карты в точке, WaitHandle на самом деле используется затем, можно повредить эту цепочку.
Это в основном, что происходит, когда Вы смешиваете Состав или Агрегирование с Доступными классами. Как упомянуто, первый выход должен был бы осуществить рефакторинг waitHandle из шнурка.
Однако можно разделить вниз Доступный шаблон значительно, когда у Вас нет неуправляемых ресурсов. (Я все еще ищу официальную ссылку для этого.)
Но можно опустить деструктор и GC.SuppressFinalize (это); и возможно очистка виртуальная пустота Располагает (bool располагающий) немного.
Это чувствует много как высокоуровневые вопросы проектирования, как это часто бывает когда "быстрое исправление" опускается до болота. Для большего количества обсуждения путей, Вы могли бы найти этот поток полезным.
Интересно, если Driver
определяется как выше:
class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}
Затем, когда Shoe
сделан IDisposable
, FxCop (v1.36) не жалуется это Driver
должен также быть IDisposable
.
Однако, если это определяется как это:
class Driver
{
Shoe leftShoe = new Shoe();
Shoe rightShoe = new Shoe();
}
затем это будет жаловаться.
Я подозреваю, что это - просто ограничение FxCop, а не решение, потому что в первой версии Shoe
экземпляры все еще создаются Driver
и все еще потребность, которая будет расположена так или иначе.
Я не думаю, что есть технический способ предотвратить распространение IDisposable, если вы держите вашу конструкцию так плотно связаны. Тогда стоит задуматься, правильна ли конструкция.
В вашем примере, я думаю, имеет смысл иметь шнурок для обуви, и, возможно, водитель должен иметь свою обувь. Однако автобус не должен владеть водителем. Обычно водители автобусов не следуют за автобусами до свалки :). В случае с водителями и обувью, водители редко делают свою собственную обувь, то есть на самом деле они не "владеют" своей обувью.
Альтернативная конструкция может быть:
class Bus
{
IDriver busDriver = null;
public void SetDriver(IDriver d) { busDriver = d; }
}
class Driver : IDriver
{
IShoePair shoes = null;
public void PutShoesOn(IShoePair p) { shoes = p; }
}
class ShoePairWithDisposableLaces : IShoePair, IDisposable
{
Shoelace lace = new Shoelace();
}
class Shoelace : IDisposable
{
...
}
Новая конструкция, к сожалению, является более сложной, так как она требует дополнительных классов для инстанцирования и утилизации конкретных экземпляров обуви и водителей, но это осложнение присуще решаемой проблеме. Хорошо то, что автобусы больше не нужно выбрасывать просто для того, чтобы избавиться от шнурков.
Чтобы предотвратить распространение IDisposable
, вы должны попытаться инкапсулировать использование одноразового объекта внутри одного метода. Попробуйте спроектировать Shoelace
по-другому:
class Shoelace {
bool tied = false;
public void Tie() {
using (var waitHandle = new AutoResetEvent(false)) {
// you can even pass the disposable to other methods
OtherMethod(waitHandle);
// or hold it in a field (but FxCop will complain that your class is not disposable),
// as long as you take control of its lifecycle
_waitHandle = waitHandle;
OtherMethodThatUsesTheWaitHandleFromTheField();
}
}
}
Область применения ручки ожидания ограничена методом Tie
, и классу не нужно иметь одноразовое поле, а значит, не нужно быть одноразовым самому.
Поскольку ручка ожидания является деталью реализации внутри Shoelace
, она не должна каким-либо образом изменять его публичный интерфейс, например, добавлять новый интерфейс в его объявление. Что произойдет, когда вам больше не понадобится одноразовое поле, удалите ли вы объявление IDisposable
? Если вы подумаете об Shoelace
абстракции, то быстро поймете, что она не должна быть загрязнена инфраструктурными зависимостями, такими как IDisposable
. IDisposable
следует зарезервировать для классов, чья абстракция инкапсулирует ресурс, требующий детерминированной очистки; т.е. для классов, где одноразовость является частью абстракции.