My first generic function in VB.NET
Как написать свой Дженерик на VB? Этого я пока не знаю и пытаюсь в данный момент этому научится.
Обычно все языки поддерживают макроопределения, которые достаточно ПРОСТО позволяют применить ОДИН алгоритм в нескольким типам данных, без потери контроля типов.
Например берем вот этот алгоритм - он просто работает с разными свойствами одного и того же обьекта. И соответственно имеет чуть-чуть разные названия.
00001: 'Рекурсивный обход дерева в поисках нужного тега 00002: Private Function GetNodesForTag(ByVal StartNode As system.web.SiteMapNode, ByVal TableIndex As Integer) As System.Web.SiteMapNode 00003: If StartNode.ResourceKey = TableIndex Then Return StartNode 00004: If StartNode.ChildNodes IsNot Nothing Then 00005: For Each X As system.web.SiteMapNode In StartNode.ChildNodes 00006: If X.ResourceKey = TableIndex Then 00007: Return X 00008: Else 00009: 'обход в глубину - сразу же проверяем его дочек 00010: Dim Y As system.web.SiteMapNode = GetNodesForTag(X, TableIndex) 00011: If Y IsNot Nothing Then Return Y 00012: End If 00013: Next 00014: End If 00015: End Functionи берем второй ПОХОЖИЙ код.
00001: 'Рекурсивный обход дерева в поисках нужного URL 00002: Private Function GetNodesForURL(ByVal StartNode As system.web.SiteMapNode, ByVal URL As String) As System.Web.SiteMapNode 00003: If StartNode.URL = URL Then Return StartNode 00004: If StartNode.ChildNodes IsNot Nothing Then 00005: For Each X As system.web.SiteMapNode In StartNode.ChildNodes 00006: If X.Url = URL Then 00007: Return X 00008: Else 00009: 'обход в глубину - сразу же проверяем его дочек 00010: Dim Y As system.web.SiteMapNode = GetNodesForURL(X, URL) 00011: If Y IsNot Nothing Then Return Y 00012: End If 00013: Next 00014: End If 00015: End FunctionОбычно, так было всегда - даже ТРИДЦАТЬ лет назад, этот единый алгоритм превращатся в ОДИН кусок кода вот таким образом.
1.Делается вот такой макрос.
00000: Search Macro &Pref , &Property , &Type 00001: 'Рекурсивный обход дерева в поисках нужного &Type 00002: Private Function GetNodesFor&Pref(ByVal StartNode As System.Web.SiteMapNode, ByVal URL As &Type) As System.Web.SiteMapNode 00003: If StartNode.&Property= URL Then Return StartNode 00004: If StartNode.ChildNodes IsNot Nothing Then 00005: For Each X As System.Web.SiteMapNode In StartNode.ChildNodes 00006: If X.&Property = URL Then 00007: Return X 00008: Else 00009: 'обход в глубину - сразу же проверяем его дочек 00010: Dim Y As system.web.SiteMapNode = GetNodesFor&Pref(X, URL) 00011: If Y IsNot Nothing Then Return Y 00012: End If 00013: Next 00014: End If 00015: End Function 00000: End Macro2.Вот таким его вызовом порождается обе указанные функции. А заодно еще десяток (свойства которых есть у обьекта StartNode):
Search "Tag", "ResourceKey", "Integer" Search "URL", "URL", "String"Таким же образом мы всегда могли поступить. Всегда, пока не появилось MS со своим компилятором с C#.NET и VB.NET. Вот в этих двух фрагментах моего кода - отличия более тонкие. И делегатами их не разрешить.
00001: Shared Sub FillTree(ByVal CurrentTovar As WorkingTovar, ByRef Tv1 As System.Web.UI.WebControls.TreeView) 00002: For i As Integer = 0 To CurrentTovar.PriceDS.MyBlock.Count - 1 00003: Dim X As New TreeNode 00004: X.SelectAction = TreeNodeSelectAction.Expand 00005: X.Text = CurrentTovar.PriceDS.MyBlock(i).Gname 00006: X.Value = "MyBlock_i=" & CurrentTovar.PriceDS.MyBlock(i).i.ToString 00007: For j As Integer = 0 To CurrentTovar.PriceDS.MyFieldsList.Count - 1 00008: If CurrentTovar.PriceDS.MyFieldsList(j).ToBlock = CurrentTovar.PriceDS.MyBlock(i).i Then 00009: For k As Integer = 0 To CurrentTovar.PriceDS.MyFields.Count - 1 00010: If CurrentTovar.PriceDS.MyFields(k).i = CurrentTovar.PriceDS.MyFieldsList(j).ToFields Then 00011: Dim Y As New TreeNode 00012: Y.SelectAction = TreeNodeSelectAction.Expand 00013: Y.Text = CurrentTovar.PriceDS.MyFields(k).Fname & " : " 00014: For l As Integer = 0 To CurrentTovar.PriceDS.MyValueList.Count - 1 00015: If CurrentTovar.PriceDS.MyValueList(l).ToFields = CurrentTovar.PriceDS.MyFieldsList(j).ToFields Then 00016: For m As Integer = 0 To CurrentTovar.PriceDS.MyValue.Count - 1 00017: If CurrentTovar.PriceDS.MyValue(m).i = CurrentTovar.PriceDS.MyValueList(l).ToValue Then 00018: Try 00019: Y.Text &= CurrentTovar.PriceDS.MyValue(m).VValue 00020: Y.Value = "MyBlock_i=" & CurrentTovar.PriceDS.MyBlock(i).i.ToString & ",MyFields_i=" & CurrentTovar.PriceDS.MyFields(k).i.ToString & ",MyValue_I=" & CurrentTovar.PriceDS.MyValue(m).i.ToString 00021: Catch n As System.Data.StrongTypingException 00022: End Try 00023: End If 00024: Next 00025: End If 00026: Next 00027: X.ChildNodes.Add(Y) 00028: End If 00029: Next 00030: End If 00031: Next 00032: Tv1.Nodes.Add(X) 00033: Next 00034: End Sub
00001: Shared Sub FillTree(ByVal CurrentTovar As WorkingTovar, ByRef Tv1 As System.Windows.Forms.TreeView) 00002: For i As Integer = 0 To CurrentTovar.PriceDS.MyBlock.Count - 1 00003: Dim X As New System.Windows.Forms.TreeNode 00004: X.Text = CurrentTovar.PriceDS.MyBlock(i).Gname 00005: X.Name = "MyBlock_i=" & CurrentTovar.PriceDS.MyBlock(i).i.ToString 00006: For j As Integer = 0 To CurrentTovar.PriceDS.MyFieldsList.Count - 1 00007: If CurrentTovar.PriceDS.MyFieldsList(j).ToBlock = CurrentTovar.PriceDS.MyBlock(i).i Then 00008: For k As Integer = 0 To CurrentTovar.PriceDS.MyFields.Count - 1 00009: If CurrentTovar.PriceDS.MyFields(k).i = CurrentTovar.PriceDS.MyFieldsList(j).ToFields Then 00010: Dim Y As New System.Windows.Forms.TreeNode 00011: Y.Text = CurrentTovar.PriceDS.MyFields(k).Fname & " : " 00012: For l As Integer = 0 To CurrentTovar.PriceDS.MyValueList.Count - 1 00013: If CurrentTovar.PriceDS.MyValueList(l).ToFields = CurrentTovar.PriceDS.MyFieldsList(j).ToFields Then 00014: For m As Integer = 0 To CurrentTovar.PriceDS.MyValue.Count - 1 00015: If CurrentTovar.PriceDS.MyValue(m).i = CurrentTovar.PriceDS.MyValueList(l).ToValue Then 00016: Try 00017: Y.Text &= CurrentTovar.PriceDS.MyValue(m).VValue 00018: Y.Name = "MyBlock_i=" & CurrentTovar.PriceDS.MyBlock(i).i.ToString & ",MyFields_i=" & CurrentTovar.PriceDS.MyFields(k).i.ToString & ",MyValue_I=" & CurrentTovar.PriceDS.MyValue(m).i.ToString 00019: Catch n As System.Data.StrongTypingException 00020: End Try 00021: End If 00022: Next 00023: End If 00024: Next 00025: X.Nodes.Add(Y) 00026: End If 00027: Next 00028: End If 00029: Next 00030: Tv1.Nodes.Add(X) 00031: Next 00032: End SubЗдесь присутствует и две лишние строчки кода, и разный тип параметров и чуть чуть различающийся ключик.
Но алгоритм-то явно один, хоть и с крошечной модификацией.
Не могу понять как из этих двух кусков кода сделать ДЕЙСТВИТЕЛЬНО ОДНУ программу. Ведь архи-важный принцип программирования - ПОВТОРНОЕ ИСПОЛЬЗОВАНИЕ КОДА. Не спорю, возможно это делается. Но этот принцип нарушается в MS-технологиях ПОВСЕМЕСТНО:
- Мы делаем обычный контрол в ASP2(не Custom, конечно), надеясь использовать его в другом проекте, но оказывается это нельзя.
- Мы пытаемся сделать перегруженные функции, но это приводит к тысяче строк кода вместо 80.
- Мы пытаемся создать из двух вышеприведенных кусков кода ОДИН - и погружаемся в такую БЕЗДНУ рефлекшен и ран-тайм типов (причем предварительно вообще отключив проверку типа входного параметра) - что страшно становится.
Хотя, не исключено, что я просто не уловил задумки - как именно эти два фрагмента кода свести В ОДИН...
|