Здравствуйте, Кирилл Осенков, Вы писали:
КО>А что, больше к дизайну VB как к языку претензий нет?
Это всё фигня по сравнению с разгильдяйством F# в плане свойств:
namespace FooBar
[<System.Reflection.DefaultMemberAttribute("DefaultIndexer")>]
type Foo =
new(value : int) = { x = value }
val mutable x : int
member this.Magic (* different accessor types *)with get () : int = this.x
and set (s : string) = printfn "%s" s
member this.DefaultIndexer
with get (index : int) = this.x
and set (index : int) (x : int) = ()
member this.NamedIndexer
with get (index : int) = this.x
and set (index : int) (x : int) = ()
C# одуревает от таких свойств, R# не может заменить var на явную аннотацию типа
var x = foo.Magic;
// Property, indexer, or event 'Magic' is not supported by the language;
// try directly calling accessor methods 'FooBar.Foo.get_Magic()' or 'FooBar.Foo.set_Magic(string)'
Вдруг type inference обманет и потом из C# юзать так придётся:
int x = foo.get_Magic();
foo.set_Magic("sdsd");
Ума не приложу почему не проверяется идентичность типов акцессоров
Как-то пропустил этот кусочек сначала.
Хотя в том же VB.NET индексные свойства не мешают.
ИМХО, иногда проще был бы именованный индексер, чем плодить лишние классы.
Здравствуйте, gecko, Вы писали:
G>Тогда возникает другой вопрос: а зачем было в Бейсике это вводить? Почему там не нужно "separate the responsibilities", а в C# нужно?
Здравствуйте, Кирилл Осенков, Вы писали:
OG>>А если в VB.NET объявить свойство с параметрами, то из C# его нельзя вызвать таким образом, как я понимаю. Так?
КО>Почему же. Можно. Отчасти для этого фичу и сделали.
У меня свойства из COM вызываются, а из VB.NET — не вызываются. Покажи код, как можно определить свойство с параметрами в VB.NET и вызвать его из C# 4.0.
OG>>>А если в VB.NET объявить свойство с параметрами, то из C# его нельзя вызвать таким образом, как я понимаю. Так?
КО>>Почему же. Можно. Отчасти для этого фичу и сделали.
N>У меня свойства из COM вызываются, а из VB.NET — не вызываются. Покажи код, как можно определить свойство с параметрами в VB.NET и вызвать его из C# 4.0.
В общем, я оплошал. Сорри за дезинформацию Мы действительно только поддерживаем свойства, объявленные в COM. Схитрить можно, поставив атрибут <ComImport> _ в VB, но эта лазейка не рекомендуется.
Рассказываю детали.
Когда фичу писали (это было в мае 2009), стало понятно, что добавить полноценную поддержку вызова свойств из VB и пр. очень рискованно, т.к. не успеем всё оттестировать. В VB фазовое пространство возможных свойств несравнимо больше чем тех, которые могут быть объявлены через COM. Например, в COM всё public, а в VB можно объявить protected internal setter, и пр. и пр. Так что приняли осознанное решение делать фичу только для COM и поддержку VB явно закрыли (потребовав [ComImport] на импортируемом свойстве). Фича планировалась как DCR (т.е. last-minute обновление небольшого масштаба), поэтому урезали как могли. Бюджет тоже был так себе (три недели двух тестеров), плюс три недели 2-х девелоперов (compiler + IDE). Сейчас пишу и кажется, что это много, ан нет, это на самом деле очень мало. Написать автоматизацию плюс тесты, плюс всё ручное тестирование и пр. И так с трудом успели.
В общем не знаю, годится ли это как оправдание, но что есть, то есть Я запутался, потому что сначала поддержка VB была, и я её тестировал, но потом мы её закрыли, а когда я писал блог, то про это забыл
А что, это сильно надо? Если много народу ругаться будут, может имеет смысл suggestion открыть для Dev11?
Здравствуйте, Pro100Oleh, Вы писали:
Q>>Зачем?
PO>Поддерживаю. Действительно, зачем? Раньше как-то обходился. То, что некоторые удобства есть я не спорю, но теперь будут возникать путаницы — в каком классе реализован индексатор:
Т.к. поскипанный код нельзя объявить в шарпе, то и путаницы никакой не должно быть.
КО>A common question that we expect we’ll be getting is “why just consume? why not allow to declare such properties in C#?”. Well, the answer is not even that we first have to cost, design, spec, prototype, implement and test this feature, but rather that we think that declaring a type with an indexer is a preferred approach. It’s useful to separate the responsibilities:
КО>
The property is there to get an object. The property belongs to the parent object.
КО> The indexer is there on the returned object to enumerate it. The indexer belongs to the returned object.
КО>We shouldn’t be mixing these together.
Тогда возникает другой вопрос: а зачем было в Бейсике это вводить? Почему там не нужно "separate the responsibilities", а в C# нужно?
Здравствуйте, Кирилл Осенков, Вы писали:
КО>Мы в Beta 2 добавили новую фичу в язык: теперь можно вызывать свойства с параметрами при помощи синтаксиса индексеров:
Возникает резонный вопрос.
А почему бы не добавить полноценную поддержку?
Здравствуйте, Кирилл Осенков, Вы писали:
КО>Мы в Beta 2 добавили новую фичу в язык: теперь можно вызывать свойства с параметрами при помощи синтаксиса индексеров:
Это [сабж] был большущий такой облом :о))
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Мишень-сан, Вы писали:
МС>Имелось ввиду добавление возможности не только вызова, но и объявления собственных индексных свойств.
Прошу прощения, что по-аглицки:
Why not allow declaring indexed properties in C#?
A common question that we expect we’ll be getting is “why just consume? why not allow to declare such properties in C#?”. Well, the answer is not even that we first have to cost, design, spec, prototype, implement and test this feature, but rather that we think that declaring a type with an indexer is a preferred approach. It’s useful to separate the responsibilities:
The property is there to get an object. The property belongs to the parent object.
The indexer is there on the returned object to enumerate it. The indexer belongs to the returned object.
We shouldn’t be mixing these together.
Здравствуйте, Кирилл Осенков, Вы писали:
КО>Мы в Beta 2 добавили новую фичу в язык: теперь можно вызывать свойства с параметрами при помощи синтаксиса индексеров:
КО>
КО>// до
КО>excel.get_Range("A1").set_Value(Type.Missing, "ID");
КО>// после
КО>excel.Range["A1"].Value = "ID";
КО>
А если excel будет иметь тип dynamic, это будет работать?
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Кирилл Осенков, Вы писали:
КО>>Мы в Beta 2 добавили новую фичу в язык...
Q>Зачем?
Поддерживаю. Действительно, зачем? Раньше как-то обходился. То, что некоторые удобства есть я не спорю, но теперь будут возникать путаницы — в каком классе реализован индексатор:
class MyRange
{
public int this[int index]
{
get {return 0;}
}
}
class Excel
{
public MyRange MyRange {get;set;}
public int Range[int index] //типа новая фича
}
........
Excel excel = CreateExcel(...);
int a = excel.Range[13];
int b = excel.MyRange[13];
ЗЫ: я так понял, что это лишь фича языка C#, а реализуется все теми же индексаторами (или свойствами с параметрами, как они еще описаны у Рихтера).
Здравствуйте, Oksana Gimmel, Вы писали:
КО>>Мы в Beta 2 добавили новую фичу в язык: теперь можно вызывать свойства с параметрами при помощи синтаксиса индексеров:
КО>>// до
КО>>excel.get_Range("A1").set_Value(Type.Missing, "ID");
КО>>// после
КО>>excel.Range["A1"].Value = "ID";
OG>А если excel будет иметь тип dynamic, это будет работать?
Работает:
var app = new Microsoft.Office.Interop.Excel.Application();
dynamic book = app.Workbooks.Add();
dynamic sheet = book.Worksheets.Add();
sheet.Range["A2"] = "Test!";
book.SaveAs(@"C:\Temp\Test2.xls");
book.Close();
app.Quit();
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Pro100Oleh, Вы писали:
Q>>>Зачем?
PO>>Поддерживаю. Действительно, зачем? Раньше как-то обходился. То, что некоторые удобства есть я не спорю, но теперь будут возникать путаницы — в каком классе реализован индексатор:
L>Т.к. поскипанный код нельзя объявить в шарпе, то и путаницы никакой не должно быть.
Путаница возникает при использовании (вторая часть приведенного мною кода), а не при обявлении кода. А объявить можно и не в шарпе.
Здравствуйте, gecko, Вы писали:
G>Тогда возникает другой вопрос: а зачем было в Бейсике это вводить? Почему там не нужно "separate the responsibilities", а в C# нужно?
Ну наверное уж для COM, зачем же ещё.
С появления dynamic и "улучшенной поддержки COM в C# 4.0" оное и в C# стало иметь смысл.
Я думаю вопрос должен быть такой: зачем было в VB.NET вводить возможность самому определять такие свойства?
Здравствуйте, Пельмешко, Вы писали:
П>Я думаю вопрос должен быть такой: зачем было в VB.NET вводить возможность самому определять такие свойства?
А что, больше к дизайну VB как к языку претензий нет?
По историческим причинам. Если бы ВБ с нуля дизайнили, то там вместо default properties и indexed properties тоже бы indexers и implicit conversion были бы.
Здравствуйте, Мишень-сан, Вы писали:
МС>Как-то пропустил этот кусочек сначала. МС>Хотя в том же VB.NET индексные свойства не мешают. МС>ИМХО, иногда проще был бы именованный индексер, чем плодить лишние классы.
Не только в Бэйсике. В Немерле тоже поддерживаются и проблем не вызывают.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Пельмешко, Вы писали:
П>Это всё фигня по сравнению с разгильдяйством F# в плане свойств:
Спасибо! Разбираемся!
From: Chris Smith (F#)
To: Kirill Osenkov
Subject: RE: Weirdness with F# properties
Kirill,
Your friend has stumbled upon some interesting bugs / corner cases in both the C# and F# compilers.
1. It sounds legit that the C# compiler won’t allow you to use properties that have different getter and setter types. Just like the error message says you can work around this.
2. To create a default indexer in F#, simply create a property named Item. However, that doesn’t work in the code example because they explicitly added a DefaultMemberAttribute, it looks like in that case the F# compiler adds that attribute twice which leads to problems.
3. You can have properties that take more than one parameter, just tuple them. E.g. (index : int * int * int) or (x, y, z)
I’m going to continue investigating here, but tell your friend good job for poking around in the corners
Здравствуйте, Oksana Gimmel, Вы писали:
OG>А если в VB.NET объявить свойство с параметрами, то из C# его нельзя вызвать таким образом, как я понимаю. Так?
Почему же. Можно. Отчасти для этого фичу и сделали.
Здравствуйте, nikov, Вы писали:
N>У меня свойства из COM вызываются, а из VB.NET — не вызываются. Покажи код, как можно определить свойство с параметрами в VB.NET и вызвать его из C# 4.0.
Обана. Интересно. Если на VB тип, который определяет свойство, положить ComImport, то всё работает. Без него — не работает! В понедельник приду на работу, будем разбираться... В любом случае спасибо, что обратили моё внимание
Вот так работает:
Imports System.Runtime.InteropServices
<ComImport()> _
Public Class Class1
Public Property IndexProp(ByVal p1 As Integer) As String
Get
Return Nothing
End Get
Set(ByVal value As String)
End Set
End Property
End Class