Что происходит, когда свойство ICollection инициализируется с использованием синтаксиса {value} без указания типа коллекции (массив, список и т. Д.)?

2

Пример:

Изображение 174551

Я удалил new[] тип new[] который был указан перед первой фигурной скобкой, и увидел, что этот код все еще функционирует, как и ожидалось. Я попытался воспроизвести это для некоторых других интерфейсов и типов. Мне любопытно узнать, что происходит в фоновом режиме и как/почему этот синтаксис работает, но я не совсем уверен, какие ключевые слова для поиска использовать в моих поисках.

  • 0
    На самом деле, это, кажется, приводит к исключению NullReferenceException во время выполнения. Тогда я предполагаю, что это на самом деле не работает, несмотря на компиляцию (я предполагаю, что это серия вызовов .Add (), а не создание массива, как вы могли ожидать от new []).
  • 0
    Это определенно работает для меня. Я использую SolrNet, и я вижу его, используя те результаты, когда строка запроса генерируется на основе этой информации.
Показать ещё 4 комментария
Теги:
.net-core

2 ответа

2
Лучший ответ

Из источника, с которым вы ICollection<string> Fields, мы видим, что ICollection<string> Fields инициализируется в конструкторе как List<string>:

/// <summary>
/// Common, shared query options
/// </summary>
public CommonQueryOptions() {
    Fields = new List<string>();
    FilterQueries = new List<ISolrQuery>();
    Facet = new FacetParameters();
    ExtraParams = new Dictionary<string, string>();
}

/// <summary>
/// Fields to retrieve.
/// By default, all stored fields are returned
/// </summary>
public ICollection<string> Fields { get; set; }

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

Что делает Fields = new[] { "*", "score" }, так это заменяет этот список строковым массивом, содержащим эти значения. Это работает, потому что массивы также реализуют ICollection<T>.

1

Пожалуйста, рассмотрите следующий пример:

    public class UnitTest
{
    [Fact]
    public void TestList()
    {
        var sample = new SampleList
        {
            Fields = { "b", "c" }
        };

        var count = sample.Fields.Count;
        Assert.Equal(2, count);
    }

    [Fact]
    public void TestArray()
    {
        var sample = new SampleArray
        {
            Fields = { "b", "c" }
        };

        var count = sample.Fields.Count;
        Assert.Equal(2, count);
    }
}

public class SampleList
{
    public ICollection<string> Fields { get; set; } = new List<string>
    {
        "a"
    };
}

public class SampleArray
{
    public ICollection<string> Fields { get; set; } = new string[]
    {
        "a"
    };
}

Используемый вами синтаксис работает только в инициализаторе объектов, и он пытается добавить указанные элементы в коллекцию.

  • В тестовом примере TestList() assert не выполняется, потому что он добавляет "b", "c" в список и приводит к "a", "b", "c"

  • В тестовом примере TestArray() выполнить assert не удается, поскольку он выдает следующее исключение

System.NotSupportedException: "Коллекция была фиксированного размера."

Это означает, что если вы хотите использовать этот синтаксис инициализации объекта, вы должны использовать коллекции, которые не имеют фиксированного размера.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню