Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果我们使用的所有类通常都继承自某个公共类,那么为什么我们需要泛型呢?_C#_Generics_Inheritance - Fatal编程技术网

C# 如果我们使用的所有类通常都继承自某个公共类,那么为什么我们需要泛型呢?

C# 如果我们使用的所有类通常都继承自某个公共类,那么为什么我们需要泛型呢?,c#,generics,inheritance,C#,Generics,Inheritance,你好。泛型通常是这样使用的: class MyList<T> { public T data; public MyList<T> nextElement; } 甚至: class MyStructure<T> where T : SomeCommonClass { public T data; public MyStructure<T> nextElement; public MyStructure<

你好。泛型通常是这样使用的:

class MyList<T>
{
    public T data;
    public MyList<T> nextElement;
}
甚至:

class MyStructure<T> where T : SomeCommonClass
{
    public T data;
    public MyStructure<T> nextElement;
    public MyStructure<T> prevElement;
}
更新:

好吧,恐怕你没有完全正确地理解我,甚至把我的问题降级了。没有泛型的示例,可以正常工作:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        MyNode nodeButton = new MyNode("nodeButton", new Button());
        MyNode nodeTextBox = new MyNode("nodeTextBox", new TextBox());
        MyNode nodeCheckBox = new MyNode("nodeCheckBox", new CheckBox());
        MyList myList = new MyList() { nodeButton, nodeTextBox, nodeCheckBox };
        for (int i = 0; i < myList.Count;i++)
        {
            this.Controls.Add(myList[i].Data);
            myList[i].Data.Left = 100 * i;
        }
    }
}

public class MyNode
{
    public MyNode(string name, Control data)
    {
        Data = data;
        Name = name;
    }
    public string Name { get; private set; }
    public Control Data { get; private set; }
}

public class MyList : Collection<MyNode>
{
    protected override void InsertItem(int index, MyNode item)
    {
        base.InsertItem(index, item);
        item.Data.MouseClick += new MouseEventHandler((sender, e) => { MessageBox.Show(item.Name); });
    }
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
MyNode nodeButton=新建MyNode(“nodeButton”,new Button());
MyNode nodeTextBox=newmynode(“nodeTextBox”,newtextbox());
MyNode nodeCheckBox=新建MyNode(“nodeCheckBox”,new CheckBox());
MyList MyList=new MyList(){nodeButton,nodeTextBox,nodeCheckBox};
for(int i=0;i{MessageBox.Show(item.Name);});
}
}
与泛型的示例相同,它在编译时生成错误:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        MyNode<Button> nodeButton = new MyNode<Button>("nodeButton", new Button());
        MyNode<TextBox> nodeTextBox = new MyNode<TextBox>("nodeTextBox", new TextBox());
        MyNode<CheckBox> nodeCheckBox = new MyNode<CheckBox>("nodeCheckBox", new CheckBox());
        MyList myList = new MyList() { (MyNode<Control>)nodeButton, (MyNode<Control>)nodeTextBox, (MyNode<Control>)nodeCheckBox };
        for (int i = 0; i < myList.Count;i++)
        {
            this.Controls.Add(myList[i].Data);
            myList[i].Data.Left = 100 * i;
        }
    }
}

public class MyNode<T> where T : Control
{
    public MyNode(string name, T data)
    {
        Data = data;
        Name = name;
    }
    public string Name { get; private set; }
    public T Data { get; private set; }
}

public class MyList : Collection<MyNode<Control>>
{
    protected override void InsertItem(int index, MyNode<Control> item)
    {
        base.InsertItem(index, item);
        item.Data.MouseClick += new MouseEventHandler((sender, e) => { MessageBox.Show(item.Name); });
    }
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
MyNode nodeButton=新建MyNode(“nodeButton”,new Button());
MyNode nodeTextBox=newmynode(“nodeTextBox”,newtextbox());
MyNode nodeCheckBox=新建MyNode(“nodeCheckBox”,new CheckBox());
MyList MyList=new MyList(){(MyNode)nodeButton,(MyNode)nodeTextBox,(MyNode)nodeCheckBox};
for(int i=0;i{MessageBox.Show(item.Name);});
}
}

根据您的说法,第一个版本是不好的做法,因为类型安全性被破坏,但第二个版本不允许类型转换

在这两种情况下,您可能会丢失有关对象的大量信息,并因此丢失大量类型安全性。演员阵容不好。您还无法确保列表仅包含特定类型的对象

当使用值类型时,也会有显著的性能损失;它们必须装入
对象中或从
对象中取出,这既慢又不安全

事实上,你的建议确实存在(好吧,仍然存在)!它被叫来了,非常可怕。

来自MSDN

泛型允许您根据其作用的精确数据类型定制方法、类、结构或接口

当您将某个对象声明为
对象时,在执行特定于类型的操作之前,需要将其强制转换为适当的数据类型。类似地,在使用派生类的示例中,如果只使用基类,则会失去使用派生类属性的能力,从而使其毫无意义

在文件中进一步明确提到了一个优点:

创建泛型类的实例时,指定要替换类型参数的实际类型。这将建立一个新的泛型类,称为构造的泛型类,并在类型参数出现的任何地方替换您选择的类型。结果是一个类型安全类,它是根据您选择的类型定制的

这意味着您在代码中获得了类型安全性。同时,您可以获得高度可重用的代码,因为您只需要插入适当的类型


参考:

,因为您可以使用通用列表执行此操作:

int sum = 0;
List<int> list = GetList();
foreach(var item in list) // the compiler knows this is an int
{
    sum += item; // This would not be possible with an `object`
}
int和=0;
List=GetList();
foreach(列表中的var项)//编译器知道这是一个int
{
sum+=item;//对于`对象,这是不可能的`
}

请注意,允许编译器知道我的列表是什么类型,这使得我可以处理列表中的对象,否则需要强制转换。由于我在编译时知道要处理什么类型的对象,因此在运行此代码之前,如果我尝试执行不允许执行的操作,我可以捕获错误。

泛型提供了很多好处,例如类型安全和避免装箱和拆箱。泛型与使用对象相比速度更快,因为它避免了装箱和拆箱。要了解更多关于这些好处的详细信息,请参阅,如果您是新手,请访问以下链接:

更新:

如果您理解类型安全的正确含义,那么您就不难理解
泛型
purpose完全不允许用户对对象进行类型转换。如果您对类型转换非常确定,那么您可以在
MyNode
类中编写自己的
Cast()
方法,该方法可以将类型
MyNode
转换为
MyNode
。如果您了解该场景,并且对类型和铸件非常确定,并且知道未来的更改不会与当前的更改冲突,那么不要使用
泛型。在编程中,我们不能在每个地方都使用所有东西,这完全取决于场景,并且使用了最适合场景的实践。所以你应该使用public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        MyNode<Button> nodeButton = new MyNode<Button>("nodeButton", new Button());
        MyNode<TextBox> nodeTextBox = new MyNode<TextBox>("nodeTextBox", new TextBox());
        MyNode<CheckBox> nodeCheckBox = new MyNode<CheckBox>("nodeCheckBox", new CheckBox());
        MyList myList = new MyList() { (MyNode<Control>)nodeButton, (MyNode<Control>)nodeTextBox, (MyNode<Control>)nodeCheckBox };
        for (int i = 0; i < myList.Count;i++)
        {
            this.Controls.Add(myList[i].Data);
            myList[i].Data.Left = 100 * i;
        }
    }
}

public class MyNode<T> where T : Control
{
    public MyNode(string name, T data)
    {
        Data = data;
        Name = name;
    }
    public string Name { get; private set; }
    public T Data { get; private set; }
}

public class MyList : Collection<MyNode<Control>>
{
    protected override void InsertItem(int index, MyNode<Control> item)
    {
        base.InsertItem(index, item);
        item.Data.MouseClick += new MouseEventHandler((sender, e) => { MessageBox.Show(item.Name); });
    }
}
int sum = 0;
List<int> list = GetList();
foreach(var item in list) // the compiler knows this is an int
{
    sum += item; // This would not be possible with an `object`
}