#c# #winforms
Вопрос:
Извините за мое очень плохо написанное название, я начинающий программист и только начал работать над приложением winforms на c#. В одной функции я создаю объект определенного типа, а затем в других функциях я перебираю список объектов этого типа, однако я переключаю тип используемого элемента управления, и когда я это делаю, мне нужно изменить объявление типа моего объекта более чем в двадцати местах. Есть ли способ создать переменную, содержащую этот тип, и определить все мои объекты с помощью этой переменной, чтобы мне нужно было указать тип только один раз, а затем изменить эту переменную. Поскольку я использую элементы управления winforms в качестве типов классов, все функции, которые я вызываю, одинаковы независимо от типа моих объектов, поэтому все, что мне нужно сделать, это изменить объявление типа, и все, извините, если это глупый вопрос, и любая помощь будет признательна.
Вот фрагмент моего кода для контекста:
private void function1(object sender, EventArgs e) //not my actual function because the real function has lots of other unrelated code { ListView PlaceType = new ListView(); // these ListView types i would like to replace with a placeholder if possible ListView listview = new ListView(); int count2 = autolayoutGroups.Controls.OfTypelt;ListViewgt;().ToList().Count(); listview.Size = new System.Drawing.Size(150, 100); listview.BackColor = normalColor; listview.BorderStyle = BorderStyle.Fixed3D; listview.ForeColor = System.Drawing.Color.Black; listview.Name = "Group" count2; listview.MouseDown = Select; } private void function2(object sender, EventArgs e) { Listlt;ListViewgt; list_of_groups = autolayoutGroups.Controls.OfTypelt;ListViewgt;().ToList(); // a place where I need some type of placeholder foreach (ListView l in list_of_groups) { // do something here } } private void function3(object sender, EventArgs e) // I have several functions like this //and if I change the control I'm using I have to change the types in every function { Listlt;ListViewgt; list_of_groups = autolayoutGroups.Controls.OfTypelt;ListViewgt;().ToList(); // a place where I need some type of placeholder foreach (ListView l in list_of_groups) { // do something here } }
Комментарии:
1. Я переключаю тип управления, который я использую — как часто, реально?
2. Я не уверен, может быть, 4-5 раз до сих пор, плюс было бы неплохо знать на будущее, я помню какой-то урок программирования некоторое время назад о том, как, если вам нужно изменить одно и то же значение в нескольких местах, а затем заменить это значение переменной.
Ответ №1:
Если я правильно понимаю вашу проблему, в настоящее время у вас есть некоторый код, в котором вы используете ListView, и вам нужен тот же код, но вместо ListView вам нужен какой-то другой класс, например, DataGridView или поле со списком. Конечно, этот другой класс также должен иметь методы, которые вы использовали в представлении списка.
В C# это понятие называется общим. У вас есть универсальные классы и универсальные методы.
Вы определяете универсальный тип, вводя идентификатор вместо детали, которую хотите заменить другим типом.
В вашем случае: вы хотите заменить ListView на DataGridView. В функции 1 вы создаете представление списка и задаете некоторые свойства. Сначала мы поместим это создание в отдельный метод, у вас будет что-то вроде этого:
private ListView CreateListView() { ListView listview = new ListView(); int count2 = autolayoutGroups.Controls.OfTypelt;ListViewgt;().Count(); listview.Size = new System.Drawing.Size(150, 100); listview.BackColor = normalColor; listview.BorderStyle = BorderStyle.Fixed3D; listview.ForeColor = System.Drawing.Color.Black; listview.Name = "Group" count2; listview.MouseDown = Select; return listView; } private void function1(object sender, EventArgs e) { ListView createdListView = this.CreateListView(); // TODO: do something with the created ListView }
(Небольшая оптимизация, выходит за рамки вопроса): чтобы вычислить количество 2, не создавайте список всех просмотров списков, а затем подсчитывайте их; используйте Count()
на IEnumerablelt;ListViewgt;
.
Чтобы изменить CreateListView таким образом, чтобы он мог создавать что-либо типа TMyType, определите универсальный метод следующим образом:
private TMyType Createlt;TMyTypegt;() { TMyType createdObject = new TMyType(); int count2 = autolayoutGroups.Controls .OfTypelt;TMyTypegt;() .Count(); createdObject.Size = new System.Drawing.Size(150, 100); createdObject.BackColor = normalColor; createdObject.BorderStyle = BorderStyle.Fixed3D; createdObject.ForeColor = System.Drawing.Color.Black; createdObject.Name = "Group" count2; createdObject.MouseDown = Select; return createdObject ; }
Поэтому все, что я сделал , это то , что всякий раз, когда я сохранял ListView
, я заменял его TMyType
типом, который должен быть создан.
Использование:
ListView createdListView = this.Createlt;ListViewgt;(); DataGridView createdDataGridView = this.Createlt;DataGridViewgt;(); ComboBox createdComboBox = this.Createlt;ComboBoxgt;();
Есть только одна проблема. Вам придется сообщить компилятору, что у TMyType есть конструктор по умолчанию (который вы хотите сделать new TMyControl()
), и у него есть такие методы, как Size
, BackColor
, ForeColor
и т. Д.
Если TMyType будет производным от класса Control
, то вы будете уверены, что у него есть нужный конструктор и он знает все методы, которые вам нужно использовать.
Чтобы сказать, что универсальный тип является производным от определенного типа, вы используете следующую структуру:
private TMyType Createlt;TMyTypegt;() where TMyType: Control { // because you are certain the TMyType is derived from Control // you can use all methods of class Control }
Это ответ на ваш вопрос: создайте универсальный метод
Некоторые другие вещи о дженериках
Другой пример: Если вы хотите сообщить компилятору, что универсальный тип реализует IComparable
:
private T Processlt;Tgt;(T input) where T: IComparable {...}
Или несколько:
private T Processlt;Tgt;(T input) where T: IComparable, IEquatable {...}
И, наконец, если вы хотите, чтобы универсальный тип имел конструктор по умолчанию:
private T Processlt;Tgt; () where T: new
Ответ №2:
На самом деле не совсем ясно, какова цель, но я полагаю, что вы можете создать свойство, которое возвращает ваш часто используемый список:
private Listlt;ListViewgt; AutolayoutGroupControls =gt; autolayoutGroups.Controls.OfTypelt;ListViewgt;().ToList()
Тогда вы сможете
foreach(var lv in AutolayoutGroupControls)} ... }
Но это мало что дает; если вы измените эту опору, чтобы вернуть что-то еще, вам все равно придется внести кучу изменений. Если ваши циклы всегда делают одно и то же, поместите его в метод и вызовите его из N обработчиков событий