在c#中输入类型 [英] Type casting in c#

查看:65
本文介绍了在c#中输入类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,



我有一个声明:

Class1 c = new Object(); ////这会导致错误,因为Class1是对象的派生类型,所以我必须这样做:



Class1 c =(Class1)new Object() ;



但如果我这样做:



对象o =新Class1(); ///这工作



嗯,第一个声明不起作用,因为CLR不允许这样做。为什么会这样?





谢谢

Hello,

I have a statement:
Class1 c = new Object(); ////this will cause an error this is because Class1 is object's derived type so i will have to do:

Class1 c = (Class1) new Object();

But if i do :

Object o = new Class1();/// this works

Well, the first statement wont work, because it is not allowed by CLR. Why is that so?


Thanks

推荐答案

这不是即使是真正的OOP,这也是编程的基础:继承。



成像可以分配:

This is not even real OOP, this is the very basics of programming: inheritance.

Imaging that the assignment is possible:
class MyClass {
   internal int Field;
}

MyClass instance = new object(); // imagine for a second that this is possible
// but then, this would be possible:
instance.Field = 2; // addressing not existing member



实例运行时类型实际上是 System.Object ,因此该对象没有字段字段。但是有问题的赋值会创建一个编译时类型的 MyClass 的变量,从而可以访问这个真正不存在的字段在记忆中。



虽然总是可以赋予​​一个更多派生到基类变量的赋值。我希望很清楚为什么。



-SA


Here, runtime type of instance is actually System.Object, so this object does not have the field Field. But the assignment in question would create a variable of the compile-time type of MyClass, giving the access to this field, which really does not exist in memory.

The assignment a variable of more derived to a variable of a base class is always possible though. I hope it's clear why.

—SA


认为'可能会有所帮助'对象是.NET中大多数构造/对象的根:包括值类型(如Integer)和引用类型(如类,集合等)。



接口和(不安全代码)指针类型和通用开放参数类型,不从Object继承。



Eric Lippert雄辩地分析了这一点论文,并非一切都来自于对象:[ ^ ]。



我们经常处理.NET中具有复杂继承级别的对象;考虑一个WinForms按钮:



System.Object

  System.MarshalByRefObject

   System .ComponentModel.Component

    System.Windows.Forms.Control

     System.Windows.Forms.ButtonBase

      System.Windows.For  System.Windows.Forms.Button



您可以想到每个Button的祖先作为可以被任何Button实例访问的曝光设施,例如方法,字段等。



说: 按钮是其所有祖先的孩子,就像说你是你祖先的孩子一样有意义。



它没有意义说你的祖父是你的孩子,并且说System.Windows.Forms.ButtonBase是一个Button的孩子是没有意义的。



因此,对象的继承树中有一个单向箭头。



我可以采用Button的任何实例,并将其作为任何对象祖先处理,这是合乎逻辑的:你可以将其视为向下投射,而当对象向下时 - 演员可能会停止曝光>由其更高级别类型提供的独特设施,它不会停止成为更高级别类型的实例。



一个例子可以帮助说明这一点:每个.NET控件都会公开一个'Tag字段,可以放置任何对象。



假设您有一个WinForm项目,以及一个TreeView实例,'treeView1,放在'Form1上。在设计时,你将一些根节点添加到TreeView。



如果你添加一个类,如下所示:
It may be helpful to think that 'Object is kind of the "root" of most of the constructs/objects in .NET: including Value Types, such as Integer, and Reference Types such as Classes, Collections, etc.

Interfaces and (unsafe code) Pointer Types, and generic "open" parameter Types, do not inherit from Object.

Eric Lippert eloquently analyzes this in his essay, "Not everything derives from object:" [^].

We are frequently dealing with objects in .NET that have complex levels of inheritance; consider a WinForms Button:

System.Object
 System.MarshalByRefObject
  System.ComponentModel.Component
   System.Windows.Forms.Control
    System.Windows.Forms.ButtonBase
     System.Windows.For System.Windows.Forms.Button

You can think of each of the "ancestors" of Button as exposing facilities that can be accessed by any instance of Button, such as Methods, Fields, etc.

It makes sense to say: "a Button is a child of all its ancestors," just as makes it sense to say that you are a child of your ancestors.

It doesn't make sense to say your grandfather is a child of you, and it doesn't make sense to say that a System.Windows.Forms.ButtonBase is a child of a Button.

So, there's a one-way arrow in an object's inheritance tree.

It's logical that I can take any instance of a Button, and deal with it as any of its object ancestors: you can think of this as down-casting, and while the object down-cast may cease to expose the unique facilities provided by its higher-level Type, it doesn't cease to be an instance of the higher-level Type.

An example may help illustrate this: every .NET Control exposes a 'Tag field into which any object can be placed.

Let's assume you have a WinForm Project, and an instance of a TreeView, 'treeView1, placed on 'Form1. At design time you add some root Nodes to the TreeView.

If you add a Class, like this:
public class TreeNodeTag
{
    public int ID { get; set; }
    public string Comments { get; set; }

    public TreeNodeTag(int id, string comments)
    {
        ID = id;
        Comments = comments;
    }
}

为您的项目,然后定义一些变量,以及Form Load事件的EventHandler,如下所示:

To your project, and then define some variables, and an EventHandler for the Form Load Event like this:

private TreeNode currentNode;
private TreeNodeTag currentNodeTag;

private void Form1_Load(object sender, EventArgs e)
{
    // the TreeView must have Nodes created in it
    // for this to work without error, and this code
    // creates Tags for only the root-level TreeNodes
    for (int i = 0; i < treeView1.Nodes.Count; i++)
    {
        currentNode = treeView1.Nodes[i];
        currentNodeTag = new TreeNodeTag(i, "comment " + i.ToString());
        currentNode.Tag = currentNodeTag;
    }
}

现在,每个根级TreeNode在其Tag属性中都有一个'TreeNodeTag实例,但是这个实例被转换为Type Object。 />


那么,如果你想以TreeNodeTag的形式访问TreeNodeTag而不是Object,那该怎么办?例如,假设你已经为TreeView定义了一个'AfterSelect EventHandler:

Now, every root-level TreeNode has an instance of a 'TreeNodeTag in its 'Tag Property, but this instance is down-cast into Type Object.

So, what if you want to access the TreeNodeTag as TreeNodeTag, not as Object: for example, assume you've defined an 'AfterSelect EventHandler for the TreeView:

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    currentNode = e.Node;
    currentNodeTag = currentNode.Tag as TreeNodeTag;

    // check to make sure we have a TreeNodeTag Type Tag object
    if(currentNodeTag == null)
    {
        MessageBox.Show(string.Format("Node: {0} does not have a Custom Tag Object", currentNode.Text));
        return;
    }

    MessageBox.Show(string.Format("Node: {0} ID: {1} Comments: {2}", currentNode.Text, currentNodeTag.ID.ToString(), currentNodeTag.Comments));
}

正如您在此代码中看到的那样,TreeNodeTag类的一个实例存储在TreeView的节点的Tag属性中作为Type'Object,但它没有剥离它的信息。



当我们检索TreeNode.Tag时,我们可以将它转换回更高级别的Type,并且可以访问存储在其中的所有信息。 br />


虽然这似乎违反了对象继承的单向性质的想法,但它实际上意味着更高级别对象中的信息可以限制使用,或通过将其转换为祖先形式来查看



希望这篇蜿蜒的文章很有用:)如果没有,我将其删除。

As you can see in this code, an instance of the TreeNodeTag Class is stored in the Tag Property of the TreeView's Nodes as Type 'Object, but it is not "stripped" of its information.

When we retrieve the TreeNode.Tag, we can cast it back to its higher-level Type, and, all the information stored in it is accessible.

While this may seem to "violate" the idea of the one-way nature of object inheritance, it really means that the information in a higher-level object can be restricted from use, or view by down-casting it to an ancestral form.

Hope this meandering essay is useful :) If not, I'll remove it.


回答在解决方案1的评论中作为后续问题提出的后续问题:



您还需要学习静态成员与实例(非静态)成员。首先,请阅读我过去的答案:

是什么让静态方法可以访问? [ ^ ],

C#windows基于这个关键词及其在应用程序中的用途 [ ^ ]。



为了说明实例字段,我们这样做:

In response to the follow-up question posed as a follow-up question in the comments to Solution 1:

You need also to learn static members vs instance (non-static) members. First of all, please read my past answers:
What makes static methods accessible?[^],
C# windows base this key word related and its uses in the application[^].

To illustrate just the instance fields, let's do this:
class MyClass {
   internal static int SomeStaticField;
   internal string SomeInstanceField;
   // before we show usage from outside of the class:
   static void SetStaticField(int value) {  // could also be non-static, be static is enough
       SomeStaticField = value; // "this." cannot be used, as if would refer the instance
       // or even
       MyClass.SomeStaticField = value;
   } 
   void SetInstanceField(string value) {
       this.SomeInstanceField = value; // and "this." can be omitted
   }
   // of course, in real software we should use properties,
   // but this was only to get into the essence of things
}

//...
// usage:

MyClass instanceOne = new MyClass();
MyClass instanceTwo = new MyClass();

instanceOne.SomeInstanceField = "first";
instanceTwo.SomeInstanceField = "second";

// now, two different instance have different values of SomeInstanceField

// but:
MyClass.SomeStaticField = 13; // is the same for all instances, this is the value per class, not per each instance

// also, you can call
MyClass.SetStaticField(14);

// or
instanceOne.SetInstaceField("some other value"); // and not visa versa, please see below





此外,您应该了解实例方法与静态方法。静态方法无法访问实例,因此它们只能调用访问同一类或结构的其他静态成员。非静态方法如何具有此访问权限?它们有额外的隐式(未明确写入的参数,表示为this),它是对您调用方法的实例的引用(参见上文:例如 instanceOne ) 。



前缀this。通常可以省略,但有时需要解决歧义,因为您还可以拥有一个局部变量或一个名称与字段完全相同的参数。这是允许的,但需要使用this进行解析。在实践中,这种冲突通常发生在构造函数参数中。



-SA


这篇关于在c#中输入类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆