Как объявить индексированное свойство по умолчанию в интерфейсе C++/CLI

как можно объявить индексированное свойство по умолчанию в интерфейсе C++/CLI.
(Прошу прощения за повторяющуюся полную нотацию с пространствами имен, потому что я только изучаю C++/CLI и хочу быть уверенным, что нет случайной путаницы языковых примитивов между C++ и C# бывает)

Код

public interface class ITestWithIndexer
{
    property System::String ^ default[System::Int32];
}

Компилятор всегда выдает "ошибка C3289: "по умолчанию" тривиальное свойство не может быть проиндексировано".
Где моя ошибка?

PS: в С# это было бы просто

public interface ITestWithIndexer
{
    System.String this[System.Int32] { get; set; }
}

Как перевести это на С++/CLI?

Спасибо!!


person Sascha    schedule 06.01.2015    source источник


Ответы (2)


В C++/CLI «тривиальное» свойство — это свойство, в котором не объявлены геттеры и сеттеры. С нетривиальным свойством геттер и сеттер объявляются явно, с синтаксисом, который больше похож на обычное объявление метода, чем на синтаксис свойств C#.

public interface class IThisIsWhatANonIndexedNonTrivialPropertyLooksLike
{
    property String^ MyProperty { String^ get(); void set(String^ value); }
};

Поскольку тривиальный синтаксис не разрешен для индексированных свойств, нам нужно сделать это для вашего индексированного свойства.

public interface class ITestWithIndexer
{
    property String^ default[int]
    {
        String^ get(int index); 
        void set(int index, String^ value);
    }
};

Вот мой тестовый код:

public ref class TestWithIndexer : public ITestWithIndexer
{
public:
    property String^ default[int] 
    {
        virtual String^ get(int index)
        {
            Debug::WriteLine("TestWithIndexer::default::get({0}) called", index);
            return index.ToString();
        }
        virtual void set(int index, String^ value)
        {
            Debug::WriteLine("TestWithIndexer::default::set({0}) = {1}", index, value);
        }
    }
};

int main(array<System::String ^> ^args)
{
    ITestWithIndexer^ test = gcnew TestWithIndexer();
    Debug::WriteLine("The indexer returned '" + test[4] + "'");
    test[5] = "foo";
}

Выход:

TestWithIndexer::default::get(4) called
The indexer returned '4'
TestWithIndexer::default::set(5) = foo
person David Yaw    schedule 06.01.2015
comment
Спасибо за подробный ответ! Решил проблему! :) - person Sascha; 07.01.2015

«Тривиальное свойство» — это свойство, для которого компилятор может автоматически генерировать геттер и сеттер, выводя их из объявления свойства. Это не может работать для индексированного свойства, компилятор понятия не имеет, что он должен делать с индексной переменной. Поэтому вы должны явно объявить геттер и сеттер. Мало чем отличается от объявления C#, за исключением синтаксического сахара. В Ecma-372, глава 25.2.2 есть пример. Адаптировано к вашему случаю:

public interface class ITestWithIndexer {
    property String ^ default[int] { 
        String^ get(int);
        void set(int, String^);
    }
};
person Hans Passant    schedule 06.01.2015
comment
Спасибо за дополнительную информацию! Иногда я чувствую себя немного избалованным компилятором C#, упуская из виду очевидные мысли, такие как проблема с обработкой переменных индекса... но, возможно, это правильно. :) - person Sascha; 07.01.2015