为什么DTO(数据传输对象)不用值类型?

中关村网名 2014-01-05 11:05:40
我们常常用Domain层的实体来体现领域也就是业务逻辑,
在Application层与UI层之间用DTO来进行数据传输。
所以DTO仅仅是用来表现数据的,那,我的疑问是:
既然仅仅是表现数据,那么为什么不用值类型呢?书上不是说类类型性能更好吗?
我的理解是,值类型数据在传递时不断被拷贝,需要更大的内存空间,
而引用类型只需要传递一个引用,占用空间更小,不知道这样理解对不对?!
...全文
600 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
中关村网名 2014-01-06
  • 打赏
  • 举报
回复
引用 11 楼 wanghui0380 的回复:
对于webform或者mvc程序员来说,DTO确实就是你说的那种功能 但是对于WPF,winfrom程序员来说,DTO就不仅仅需要那种功能了 对于WPF,winfrom程序员来说,一个对象的更改,其实可以自我保存(web没状态,而桌面程序他是有状态的) ,既然他可以自我保存,我们则不必去手动去修改他值 举个例子: web程序员通常这么写 var obj= db.getXXX() 从数据库获取对象 textbox1.text=obj.name; 如果要保存则是: obj.name=textbox1.text; 你当然认为这样的情况,这东西就是传递值 不过对于winfrom
 public partial class Form1 : Form
    { 
        MyStruct x = new MyStruct();
        MyClass x1=new MyClass();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            x.name = "a";
            x1.name="a";
            this.textBox1.DataBindings.Add("Text", x, "name");
             this.textBox2.DataBindings.Add("Text", x1, "name");

        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("结构体绑定的结果:"+x.name+"无法自动反应出更新的值");
            MessageBox.Show("引用对象绑定的结果:"+x1.name+"能自动反应出更新的值");
        }
    }

    public struct MyStruct
    {
        public string name { get; set; }
    }
    class MyClass
    {
        public string name { get; set; } 
    }
这是一个winfrom的简单窗体,运行以后你可以看到两个textbox上都绑定一个对象,这时候你更改两个textbox的值,然后点击按钮,你会发现绑定了结构体的textbox无论你输入什么,他都会弹出最初的那个值“a”,而绑定引用对象的textbox,则你输入什么他就会弹出你输入的值 ps:其实现在web方面也有mvvm化的倾向,js版的mvvm如今也在大规模运用,google有AngularJs,第3方还有KnockoutJ
我试了你的程序,确实是你说的那样。 多谢了 大牛!
wanghui0380 2014-01-06
  • 打赏
  • 举报
回复
对于webform或者mvc程序员来说,DTO确实就是你说的那种功能 但是对于WPF,winfrom程序员来说,DTO就不仅仅需要那种功能了 对于WPF,winfrom程序员来说,一个对象的更改,其实可以自我保存(web没状态,而桌面程序他是有状态的) ,既然他可以自我保存,我们则不必去手动去修改他值 举个例子: web程序员通常这么写 var obj= db.getXXX() 从数据库获取对象 textbox1.text=obj.name; 如果要保存则是: obj.name=textbox1.text; 你当然认为这样的情况,这东西就是传递值 不过对于winfrom
 public partial class Form1 : Form
    { 
        MyStruct x = new MyStruct();
        MyClass x1=new MyClass();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            x.name = "a";
            x1.name="a";
            this.textBox1.DataBindings.Add("Text", x, "name");
             this.textBox2.DataBindings.Add("Text", x1, "name");

        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("结构体绑定的结果:"+x.name+"无法自动反应出更新的值");
            MessageBox.Show("引用对象绑定的结果:"+x1.name+"能自动反应出更新的值");
        }
    }

    public struct MyStruct
    {
        public string name { get; set; }
    }
    class MyClass
    {
        public string name { get; set; } 
    }
这是一个winfrom的简单窗体,运行以后你可以看到两个textbox上都绑定一个对象,这时候你更改两个textbox的值,然后点击按钮,你会发现绑定了结构体的textbox无论你输入什么,他都会弹出最初的那个值“a”,而绑定引用对象的textbox,则你输入什么他就会弹出你输入的值 ps:其实现在web方面也有mvvm化的倾向,js版的mvvm如今也在大规模运用,google有AngularJs,第3方还有KnockoutJ
中关村网名 2014-01-06
  • 打赏
  • 举报
回复
引用 8 楼 wanghui0380 的回复:
呵呵,从来就没人说过不准传结构体,你当然可以传结构体。 作为DTO来说传结构体问题不大,因为DTO通常不需要修改里面的值,只不过作为其他场景我们会经常修改对象的值,默认能修改内部的值,总比每次写个ref,out要舒坦把
在领域驱动里面,会经常通过修改DTO的值来达到修改实体值的目的啊。 虽然我对这个也不太懂 呵呵~ 我只是对项目里面什么都使用类,而不适用结构体表较疑惑。
wanghui0380 2014-01-06
  • 打赏
  • 举报
回复
另外,class类本身还可以实现一些特定的接口,来做一些自动化的UI更新,消息同步工作 比如我们可以挂接属性更改通知,也可以挂接属性验证,挂接了这些玩意的class,可以自动完成很多代码,不在需要你去做很多很多的UI事件操作,这也是wpf里那个viewmodel的基本原理,而单纯数据使用的结构体化对象就很难具备这样的功能了
wanghui0380 2014-01-06
  • 打赏
  • 举报
回复
呵呵,从来就没人说过不准传结构体,你当然可以传结构体。 作为DTO来说传结构体问题不大,因为DTO通常不需要修改里面的值,只不过作为其他场景我们会经常修改对象的值,默认能修改内部的值,总比每次写个ref,out要舒坦把
中关村网名 2014-01-06
  • 打赏
  • 举报
回复
引用 6 楼 wanghui0380 的回复:
别纠结啥值和引用了 研究方向完全错误,你研究的方向应该是“为什么会出现DTO”而非别滴 post(我的对象 obj) 和 post(int 参数1,string 参数2) 和 post (object[] {1,"2"}) 到底谁更符合工程需要
谢谢回复! 我的疑问是为什么DTO是引用类型,我大致明白DTO的作用。 struct Student{} 照你的例子,一个post (Student student) 我传递一个结构体类型也是可以的,为什么一定是类对象呢? 我的疑问是DTO为什么是类而不是结构体?
wanghui0380 2014-01-06
  • 打赏
  • 举报
回复
别纠结啥值和引用了 研究方向完全错误,你研究的方向应该是“为什么会出现DTO”而非别滴 post(我的对象 obj) 和 post(int 参数1,string 参数2) 和 post (object[] {1,"2"}) 到底谁更符合工程需要
中关村网名 2014-01-06
  • 打赏
  • 举报
回复
引用 2 楼 qldsrx 的回复:
[quote=引用 1 楼 nonocast 的回复:] 你对DTO的理解有误,我帮你梳理一下,首先一个程序的灵魂是domain层,即通过面向对象的方法分析内在状态和行为,通过抽象和责任设定对象,此对象为BO,然后因为有界面,可能是HTML可能是WPF,而BO未必能匹配界面对象所要求的显示方式和数据源模式,所以通过VO进行适配,将BO以界面可以理解的方式展示出来。 ok,当你的程序即domain需要持久化时,因为你数据库可能是sqlite,mysqlite这样的关系数据库,也可能是文件,所以此时需要PO介入适配持久化方式。 最后当需要跨进程传递数据时,则需要用TO,因为网络或者进程间是无法传递指针,所以必须将其转化为stringify对象,这个就是TO的价值和责任。 所以每一类对象都有其价值和责任,万变不离其宗,就是保证BO的干净和纯净,只对业务负责,隔离持久化、界面和跨进程交换数据,不要为了对象而对象,都是强应果关系。 当然,最后需要一点点变通,很多简单场景下,BO是能过兼容VO,PO甚至TO,是情况而定,但道理你要懂。
什么BO\VO\PO\TO,完全不知所云。 楼主的问题很简单,只要明白两者传递方式的不同就知道了,值类型是值传递,类则是引用传递,DTO需要的是引用传递,值传递不适合,这和效率无关,你UI改动要实时反映到对象上面,必须是引用类型才能做到(大家操作的是同一个对象)。[/quote] 谢谢解答! 你说的是通过引用来实时改变我不太能够理解。 比如一个学生类Student 对应一个DTO StudentDTO, 那么,一个DTO的对象引用应该不可能指向一个实体引用吧?! 还有,我们在做报表的时候也会用一个Detail对象来,这个Detail类也可以用值类型的,为什么一般都是用的类呢? 比如说,我们要做一个成绩的报表,那么他需要Student的信息,也需要Score的信息,我们常常用一个ScoreDetail类来综合信息,我们明明可以用一个ScoreDetail值对象嘛!
nonocast 2014-01-05
  • 打赏
  • 举报
回复
你对DTO的理解有误,我帮你梳理一下,首先一个程序的灵魂是domain层,即通过面向对象的方法分析内在状态和行为,通过抽象和责任设定对象,此对象为BO,然后因为有界面,可能是HTML可能是WPF,而BO未必能匹配界面对象所要求的显示方式和数据源模式,所以通过VO进行适配,将BO以界面可以理解的方式展示出来。 ok,当你的程序即domain需要持久化时,因为你数据库可能是sqlite,mysqlite这样的关系数据库,也可能是文件,所以此时需要PO介入适配持久化方式。 最后当需要跨进程传递数据时,则需要用TO,因为网络或者进程间是无法传递指针,所以必须将其转化为stringify对象,这个就是TO的价值和责任。 所以每一类对象都有其价值和责任,万变不离其宗,就是保证BO的干净和纯净,只对业务负责,隔离持久化、界面和跨进程交换数据,不要为了对象而对象,都是强应果关系。 当然,最后需要一点点变通,很多简单场景下,BO是能过兼容VO,PO甚至TO,是情况而定,但道理你要懂。
  • 打赏
  • 举报
回复
那些int、double、byte、DictionaryEntry、DataTime之类的是值类型,因为它们是如此之“小巧”。 有些复杂类型内部的个别内嵌类型会设计为值类型,因为它确实几乎没有被以引用方式编程过(因此其不断复制内存的行为没有什么机会被触发),它只是在使用它的复杂类型中的代码中被简单使用一两下,并不被广大程序员直接重复使用。 有些复杂的递归下降分析方法,例如在linq内部使用到的分析,或者一些数学计算模型,其理论模型就要求当调用时以copy值压入堆栈。如果是引用的,那么你仍然需要用代码先复制、然后才引用传递。因此这类内部对象设计为值类型就行了。 反正是算一算声明为struct还是class分别在使用代码中的代价,取“痛苦”比较轻的哪一种。
  • 打赏
  • 举报
回复
有些搞java的人把实体对象叫做DTO。 基本上,很少使用值类型。正如你说的,它往往不是正常地引用,而是不断在内存中拷贝复制,因此非常谨慎地用值类型。 其实你可以想象一下,如果你是EF之类的框架的设计师,你会产品会自动产生成百上千个实体类型,你会生成为值类型还是引用类型?哪一种比较容易让更多程序员接受?
qldsrx 2014-01-05
  • 打赏
  • 举报
回复
引用 1 楼 nonocast 的回复:
你对DTO的理解有误,我帮你梳理一下,首先一个程序的灵魂是domain层,即通过面向对象的方法分析内在状态和行为,通过抽象和责任设定对象,此对象为BO,然后因为有界面,可能是HTML可能是WPF,而BO未必能匹配界面对象所要求的显示方式和数据源模式,所以通过VO进行适配,将BO以界面可以理解的方式展示出来。 ok,当你的程序即domain需要持久化时,因为你数据库可能是sqlite,mysqlite这样的关系数据库,也可能是文件,所以此时需要PO介入适配持久化方式。 最后当需要跨进程传递数据时,则需要用TO,因为网络或者进程间是无法传递指针,所以必须将其转化为stringify对象,这个就是TO的价值和责任。 所以每一类对象都有其价值和责任,万变不离其宗,就是保证BO的干净和纯净,只对业务负责,隔离持久化、界面和跨进程交换数据,不要为了对象而对象,都是强应果关系。 当然,最后需要一点点变通,很多简单场景下,BO是能过兼容VO,PO甚至TO,是情况而定,但道理你要懂。
什么BO\VO\PO\TO,完全不知所云。 楼主的问题很简单,只要明白两者传递方式的不同就知道了,值类型是值传递,类则是引用传递,DTO需要的是引用传递,值传递不适合,这和效率无关,你UI改动要实时反映到对象上面,必须是引用类型才能做到(大家操作的是同一个对象)。

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧