如何创建一个类型,它只是一个包含另一种类型的变量?
How to create a type that Is just a variable containing another type?
对不起,我的标题写得非常糟糕,我是一名初级程序员,我刚刚开始使用 c# winforms 应用程序。在一个函数中,我创建了某种类型的 object,然后在其他函数中,我遍历了该类型 object 的列表,但是我正在切换我正在使用的控件类型以及何时是的,我必须在二十多个地方更改 object 的类型声明。有没有一种方法可以创建一个保存该类型的变量,而不是定义我所有的 objects 关闭该变量,所以我只需要指定一次类型然后更改该变量。因为我使用 winforms 控件作为我的 class 类型,所以无论我的 object 是什么类型,我调用的所有函数都是相同的,所以我需要做的就是更改类型声明,这就是抱歉,如果这是一个愚蠢的问题,我们将不胜感激。
这是我的上下文代码片段:
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.OfType<ListView>().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)
{
List<ListView> list_of_groups = autolayoutGroups.Controls.OfType<ListView>().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
{
List<ListView> list_of_groups = autolayoutGroups.Controls.OfType<ListView>().ToList(); // a place where I need some type of placeholder
foreach (ListView l in list_of_groups)
{
// do something here
}
}
不太清楚目标是什么,但我想你可以制作一个 属性,return 是你常用的列表:
private List<ListView> AutolayoutGroupControls =>
autolayoutGroups.Controls.OfType<ListView>().ToList()
那你可以
foreach(var lv in AutolayoutGroupControls)}
...
}
但它提供的东西不多;如果您将该道具更改为 return 其他内容,您仍然需要进行大量更改。如果你的循环总是做同样的事情,把它放到一个方法中,并从 N 个事件处理程序中调用它
如果我对你的问题的理解正确,你目前有一些使用 ListView 的代码,你想要相同的代码,但你想要一些其他的 class,而不是 ListView,例如 DataGridView,或者一个组合框。当然这个其他 class 也必须有您在 ListView 上使用的方法。
在 C# 中,这个概念称为泛型。您有通用 classes 和通用方法。
您可以通过键入标识符而不是要替换为另一种类型的部分来定义泛型。
在您的情况下:您想用 DataGridView 替换 ListView。在 function1 中,您创建了一个 ListView,并设置了一些属性。首先我们将这个创建放在一个单独的方法中,你会得到这样的东西:
private ListView CreateListView()
{
ListView listview = new ListView();
int count2 = autolayoutGroups.Controls.OfType<ListView>().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
}
(小优化,题外):计算count2,不要创建所有ListView的List,然后Count它们;在 IEnumerable<ListView>
.
上使用 Count()
要更改 CreateListView 使其可以创建 TMyType 类型的任何内容,请像这样定义通用方法:
private TMyType Create<TMyType>()
{
TMyType createdObject = new TMyType();
int count2 = autolayoutGroups.Controls
.OfType<TMyType>()
.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.Create<ListView>();
DataGridView createdDataGridView = this.Create<DataGridView>();
ComboBox createdComboBox = this.Create<ComboBox>();
只有一个问题。你必须告诉编译器 TMyType 有一个默认构造函数(你想做 new TMyControl()
),并且它有像 Size
、BackColor
、ForeColor
这样的方法,等等
如果 TMyType 是从 Control
派生的 class,那么您可以确定它具有所需的构造函数并且知道您需要使用的所有方法。
要说一个泛型类型是从某个类型派生出来的,你使用下面的结构:
private TMyType Create<TMyType>() where TMyType: Control
{
// because you are certain the TMyType is derived from Control
// you can use all methods of class Control
}
这回答了你的问题:创建一个泛型方法
关于泛型的一些其他事情
再举个例子:如果你想通知编译器泛型类型实现了IComparable
:
private T Process<T>(T input) where T: IComparable {...}
或多个:
private T Process<T>(T input) where T: IComparable, IEquatable {...}
最后,如果您希望泛型类型具有默认构造函数:
private T Process<T> () where T: new
对不起,我的标题写得非常糟糕,我是一名初级程序员,我刚刚开始使用 c# winforms 应用程序。在一个函数中,我创建了某种类型的 object,然后在其他函数中,我遍历了该类型 object 的列表,但是我正在切换我正在使用的控件类型以及何时是的,我必须在二十多个地方更改 object 的类型声明。有没有一种方法可以创建一个保存该类型的变量,而不是定义我所有的 objects 关闭该变量,所以我只需要指定一次类型然后更改该变量。因为我使用 winforms 控件作为我的 class 类型,所以无论我的 object 是什么类型,我调用的所有函数都是相同的,所以我需要做的就是更改类型声明,这就是抱歉,如果这是一个愚蠢的问题,我们将不胜感激。
这是我的上下文代码片段:
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.OfType<ListView>().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)
{
List<ListView> list_of_groups = autolayoutGroups.Controls.OfType<ListView>().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
{
List<ListView> list_of_groups = autolayoutGroups.Controls.OfType<ListView>().ToList(); // a place where I need some type of placeholder
foreach (ListView l in list_of_groups)
{
// do something here
}
}
不太清楚目标是什么,但我想你可以制作一个 属性,return 是你常用的列表:
private List<ListView> AutolayoutGroupControls =>
autolayoutGroups.Controls.OfType<ListView>().ToList()
那你可以
foreach(var lv in AutolayoutGroupControls)}
...
}
但它提供的东西不多;如果您将该道具更改为 return 其他内容,您仍然需要进行大量更改。如果你的循环总是做同样的事情,把它放到一个方法中,并从 N 个事件处理程序中调用它
如果我对你的问题的理解正确,你目前有一些使用 ListView 的代码,你想要相同的代码,但你想要一些其他的 class,而不是 ListView,例如 DataGridView,或者一个组合框。当然这个其他 class 也必须有您在 ListView 上使用的方法。
在 C# 中,这个概念称为泛型。您有通用 classes 和通用方法。
您可以通过键入标识符而不是要替换为另一种类型的部分来定义泛型。
在您的情况下:您想用 DataGridView 替换 ListView。在 function1 中,您创建了一个 ListView,并设置了一些属性。首先我们将这个创建放在一个单独的方法中,你会得到这样的东西:
private ListView CreateListView()
{
ListView listview = new ListView();
int count2 = autolayoutGroups.Controls.OfType<ListView>().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
}
(小优化,题外):计算count2,不要创建所有ListView的List,然后Count它们;在 IEnumerable<ListView>
.
Count()
要更改 CreateListView 使其可以创建 TMyType 类型的任何内容,请像这样定义通用方法:
private TMyType Create<TMyType>()
{
TMyType createdObject = new TMyType();
int count2 = autolayoutGroups.Controls
.OfType<TMyType>()
.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.Create<ListView>();
DataGridView createdDataGridView = this.Create<DataGridView>();
ComboBox createdComboBox = this.Create<ComboBox>();
只有一个问题。你必须告诉编译器 TMyType 有一个默认构造函数(你想做 new TMyControl()
),并且它有像 Size
、BackColor
、ForeColor
这样的方法,等等
如果 TMyType 是从 Control
派生的 class,那么您可以确定它具有所需的构造函数并且知道您需要使用的所有方法。
要说一个泛型类型是从某个类型派生出来的,你使用下面的结构:
private TMyType Create<TMyType>() where TMyType: Control
{
// because you are certain the TMyType is derived from Control
// you can use all methods of class Control
}
这回答了你的问题:创建一个泛型方法
关于泛型的一些其他事情
再举个例子:如果你想通知编译器泛型类型实现了IComparable
:
private T Process<T>(T input) where T: IComparable {...}
或多个:
private T Process<T>(T input) where T: IComparable, IEquatable {...}
最后,如果您希望泛型类型具有默认构造函数:
private T Process<T> () where T: new