2013-06-21 3 views
2

Я знаю, что это не проблема реального мира, но мне интересно: можете ли вы получить доступ к индексу со всеми параметрами по умолчанию без отражений/трюков?Indexer с параметрами по умолчанию

Например, как позвонить:

public int this[string val="", int sth=5] 
{ 
    get 
    { 
     return 0; 
    } 
    set 
    { 
    } 
} 

без предоставления параметров в явном виде?

Я бы подумал о чем-то вроде myobject[], но это явно неверно.

Почему компилятор не предупреждает меня об отсутствии смысла?

ответ

5

Почему компилятор не предупреждает меня об отсутствии смысла?

Потому что это действительно имеет смысл, просто не в C#. Свойство по умолчанию, которое индексируется с аргументами no, легко поддерживается в COM, например. И C# - это язык, который позволяет вам реализовывать COM-серверы. Очень просто сделать, просто примените атрибут [ComVisible (true)]. Использование COM-серверов в C# также очень популярно, так как обычный интерфейс Office - interop.

Это трение существует, поскольку существует значительная проблема с такими свойствами. Синтаксис сахара очень сладкий, но, как и любой сахар, он может производить гнилые зубы. Там очень неприятный синтаксис неоднозначность при использовании такого свойства, скажем, язык сценариев:

Dim obj As New Foo 
obj = Nothing 

Что было задумано здесь? Следует ли присвоить объект Ничего? Или должно быть присвоено свойство по умолчанию Nothing? Оба абсолютно законны, компилятор не может понять, какой из них лучше. Для языков Visual Basic (VBScript, VBA, VB6) эта неоднозначность была решена путем добавления дополнительного дополнительного слова на этом языке. Вы должны использовать Set, когда вы имели в виду объект, Let или nothing, чтобы назначить свойство по умолчанию. Это заставило многих начинающих программистов, которые получили начало в сценариях, понятие «объект» просто не очень понятно для них. И, конечно, очень легко угадать, это главный генератор ошибок.

Эта проблема оказала очень пагубное влияние на ядро ​​взаимодействия, а также свойства COM могут иметь два устройства, PropPut и PropPutRef. То, что вы видите в методе IDispatch :: Invoke(). Языки .NET положили конец этому, не в последнюю очередь потому, что CLI этого не позволяет, они настаивают на том, что свойство по умолчанию должно иметь аргумент. Теперь он недвусмыслен для компилятора, он может определить, было ли назначение объекта предназначено, поскольку оно не использует аргумент индексатора.

Команде C# было особенно трудно убедить, что это должно быть изменено назад, они абсолютно ненавидят двусмысленность, а также должны. Первоначально они настаивали на том, что может быть только один индексированный объект и что это свойство должно быть быть свойством по умолчанию и иметь только один аргумент. Индексатор. Они, наконец, обрушились на версию 4, слишком много программистов, написание кода для взаимодействия с Office, для улучшения. Но взял его только по мере необходимости, хорошо в сценариях interop, но все еще не разрешен в коде C#. Вам придется называть get_Item() трудным путем. Или, конечно, просто не писать код, подобный этому ...

0

Дело в том, что, если вы думаете об этом, это имеет смысл.

Вся проблема основана на некоторых привычках, взятых из C++. Если у вас есть параметры по умолчанию, они идут в конце списка параметров. Точно так же в C#.

Основное отличие между C++ и C# заключается в том, что в последнем вы можете получить доступ к параметрам метода по именам! В отличие от C++, где вы должны предоставить все параметры в порядке, как они приходят в декларации метода, в C# это совершенно законно:

class Sth 
{ 
    public int this[string val="", int sth=5] 
    { 
     get 
     { 
      return 0; 
     } 
     set 
     { 
     } 
    } 

    public Sth() 
    { 
     var i = this[sth: 6]; 
    } 
} 

Это обозначение не было бы возможно в стандартном C++.

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

Это автоматически приводит нас к второму вопросу: как насчет индексатора только с одним параметром со значением по умолчанию?

class Sth 
{ 
    public int this[int sth=5] 
    { 
     get 
     { 
      return 0; 
     } 
     set 
     { 
     } 
    } 
} 

Мир по-прежнему здоров. Хотя мы фактически не можем использовать индексатор «правильным образом» (т. Е. Без отражения или какого-либо другого хакерского механизма), мы получаем предупреждение. На моно (и, вероятно, .NET, а) это выглядит следующим образом:

Предупреждение CS1066: никогда не будет использоваться значение по умолчанию, заданное для дополнительного параметра «СТГ» (CS1066)

Мы на самом деле не может вызывать его без предоставления явного значения параметра.

Вся проблема будет намного легче решить, если я сначала подумаю об индексетора с одним параметром. Но, ну, я этого не сделал. ;-)

 Смежные вопросы

  • Нет связанных вопросов^_^