用方法传递参数 和 通过类属性传递模拟传递参数

蹦极的馒头 2014-09-21 10:59:31
一般的,我们调用某个非静态类的有参数的方法,都是先实例化类对象,再通过类对象调用方法,并传递参数过去

最近在看到一些代码,在实现方法调用传递参数的时候,并不是很习惯用上面的方式,其代码中几乎把所有方法用到的参数都设计成属性,然后再调用方实例化类对象,并为需要的属性赋值(即上面方式的参数)

我不知道大家经常用哪种方式,这两种方式有没有什么对比优劣,或者性能问题。
...全文
438 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
smthgdin_020 2014-09-23
  • 打赏
  • 举报
回复
我不觉得这样设计有多好,甚至我觉得这样子有些代码坏味道。 1.从封装角度看。这样的方法签名,表达能力不强,没交代清楚输入,调用者需要了解被调用代码细节,才能知道需要给哪些属性赋值。如果不同程序集,不同人员一同开发会有不小沟通障碍,一旦被调用方法参数有变要通知调用方,否则可能出现bug。 2.从接口角度看。基于第一点,很难形成接口,因为接口功能之一是定义输入输出的规范。 3.从维护角度看。 首先,代码是你自己写的,自然觉得问题不大,但是如果别人来做代码的维护,单看调用不看被调用方法的代码细节,确实不知道怎么改。其次,如果被调用方法所需参数数量发生变化时,那么调用代码的对象实例的属性需要相应的新增和修改,这个做不到自动重构,需要查找引用,然后手工一个个改,可能存在漏改;如果不改,多余的属性赋值显然会影响以后阅读。如果是指明参数个数和类型,起码编译的时候可以报错。 4.从隐藏Bug角度看。基于第三点,如果被调用方法体内部对参数使用个数等的修改,然后,调用没有同步修改,可能隐含造成bug(方法体新增参数的时候,调用没有同步新增属性的赋值)。 5.从泛型编程角度看。这样子的设计,难用泛型来编程,因为你需要给具体类型的具体属性赋值后才调用方法。 如果按照这样的思路,我一般更倾向于使用实体类作为参数。例如: //以下DAO public IDAO<TEntity> where TEntity : EntitieBase, new() { Add(TEntity); Update(TEntity); } public abstract class DAOBase<TEntity, TDataContext> : IDAO<TEntity> where TEntity : EntitieBase, new() where TDataContext : DbContext, new() { protected TDataContext dataContext; public TDataContext DataContext { get { return dataContext; } } Add(TEntity) { DataContext.Add(TEntity); TEntity.ID = Guid.newd.tos(); } } public class DaoUser : DAOBase<User, EFEntities> //以下BO public abstract class BOBase<TEntity, TIDAO> where TEntity : EntitieBase where TIDAO : IDAO<TEntity> { protected ICacheManager CacheManager; protected ILogManager LogManager; protected ITranstionManager TranstionManager; protected <T>ServiceLocator { //ioc容器 } private TIDAO dao; public TIDAO Dao { get set } Add(TEntity) { Dao.Add(TEntity); } } public class BoUser : BOBase<User, DaoUser>
wanghui0380 2014-09-22
  • 打赏
  • 举报
回复
既然你喜欢传统api方式,那么我估计你会经常碰到一类很有意思的错误,也会经常接到很多很有意思的变动 1.如果你调用参数错了,请问你是怎么排错滴,20多个参数,有string,有int,还有datetime,好吧!现在报错了,请问你每次是怎么排错滴,挨个挨个数么?额,先检查数文档上有20个参数,然后在数自己这边也有20个参数,然后在数前面4个是string,我自己这边前面4个是string,挨个数完?然后如果有直接返回,在写n个out和n个ref 2.额需求变动,我需要加一个参数,或者改变参数类型,你打算怎么办?以前调用者滴代码怎么修改(好吧这个现在还好,不算很突出,有重构工具帮助解决) 3.功能差不多的api,只是参数个数和参数代表意义不同,你说可以多态??不过你碰到过参数个数一样,类型一样,这个编译器会告诉你方法签名一样,存在二义性。这个你又打算怎么办
Trent1985 2014-09-22
  • 打赏
  • 举报
回复
只是更好的封装而已!
smthgdin_020 2014-09-22
  • 打赏
  • 举报
回复
最好贴出代码吧。不然也看不出为何要那么设计。
sunny906 2014-09-22
  • 打赏
  • 举报
回复
通过给属性赋值和传递参数,只是不同的调用方式而已,linq to sql就是先给属性赋值然后调用方法
moonwrite 2014-09-22
  • 打赏
  • 举报
回复
引用 18 楼 u010401287 的回复:
那即大家都应该从面向对象的概念来用属性代替方法参数咯?
不要一刀切 举一个列子 比如 两个数相加 Add(int a, int b)// 你觉得这个好,还是下面的一个好 public class TwoNum { public int NumA; public int NumB; } Add(TwoNum nums) 我现在的设计依据是:如果参数很多~而且参数个数不固定那么用对象,反过来参数很少,而且很固定,param1 param2
蹦极的馒头 2014-09-22
  • 打赏
  • 举报
回复
那即大家都应该从面向对象的概念来用属性代替方法参数咯?
wanghui0380 2014-09-22
  • 打赏
  • 举报
回复
我5楼说的是传统api使用上的问题 下面你既然提到了面对对象,ok,我们说传统api是明显的过程式编码,你怎么会认为怎么明显的过程式代码风格会比封装滴对象更符合面对对象呢?? 对象有一个和过程式明显的区别是“抽象”,各个方法强调的是依赖抽象,而非依赖具象。比如一个用户对象,我依赖滴只是用户对象,并不依赖你里面有什么用户名啊,用户密码啊,出身年月啊。 ps:作为基本设计,只有类似math.abs,math.cos,这样具有明确含义的方法是需要确定参数滴,而且业务逻辑,其实只依赖业务抽象,而不依赖具体每一个参数。 比如 一个where,我们依赖滴是func<T,bool>,你如果俺传统api,你会写什么。你会写 参数1,参数2,如何拼接sql语句,where 参数1=xx and 参数2=xxx
  • 打赏
  • 举报
回复
引用 14 楼 sp1234 的回复:
[quote=引用 13 楼 u010401287 的回复:] 但是都强行设计成属性,那么假如我有100个方法,每个方法有5个参数,而且都不一样,那么我需要定义500个属性,也就是有500个字段,那么在实例化类时,就要为500个字段分配内存(至少是默认值),我其实只要调用其中一个方法,你这一下是不是占用内存更多了
你怎么知道人家不是弄500个class,而非得是一个class呢? 实际上你既没有理解为什么要弄class,也没有理解为什么(带参数或者无参数的)方法要定义在对象中。[/quote] 500 改为 100!
  • 打赏
  • 举报
回复
面向对象分析和设计,基于“自然”的对应物,基于系统分析。不是为了写个“编程语言方法”而写的。 仅仅从你的角度出发,永远不可能考虑到对象,更不可能面向对象地去设计的。所以你完全从“方法”、编程的角度去说,无法说通。
  • 打赏
  • 举报
回复
引用 13 楼 u010401287 的回复:
但是都强行设计成属性,那么假如我有100个方法,每个方法有5个参数,而且都不一样,那么我需要定义500个属性,也就是有500个字段,那么在实例化类时,就要为500个字段分配内存(至少是默认值),我其实只要调用其中一个方法,你这一下是不是占用内存更多了
你怎么知道人家不是弄500个class,而非得是一个class呢? 实际上你既没有理解为什么要弄class,也没有理解为什么(带参数或者无参数的)方法要定义在对象中。
蹦极的馒头 2014-09-22
  • 打赏
  • 举报
回复
引用 12 楼 Z65443344 的回复:
虽然可以再定义一个校验输入参数是否在范围内的函数,也可以实现代码比较少,不用同样的代码复制许多次 但是这样不利于扩展,比如将来还会有fun4,fun5,都要用到p1和p2, 那么如果将来定义fun4的时候,忘记将这个函数复制过来再执行一遍,不就出错了吗
那如果我一个类中方法很多,并且方法的参数千变万化,我也强行为其设计很多属性,这是不是违背面向对象概念了,其实这些属性根本和这个类没有多大关系,只是为了参数为被属性化。 同时,方法如果在运行时传递参数,只是在执行时会有参数拷贝操作或者引用传递操作,但是都强行设计成属性,那么假如我有100个方法,每个方法有5个参数,而且都不一样,那么我需要定义500个属性,也就是有500个字段,那么在实例化类时,就要为500个字段分配内存(至少是默认值),我其实只要调用其中一个方法,你这一下是不是占用内存更多了
於黾 2014-09-22
  • 打赏
  • 举报
回复
虽然可以再定义一个校验输入参数是否在范围内的函数,也可以实现代码比较少,不用同样的代码复制许多次 但是这样不利于扩展,比如将来还会有fun4,fun5,都要用到p1和p2, 那么如果将来定义fun4的时候,忘记将这个函数复制过来再执行一遍,不就出错了吗
於黾 2014-09-22
  • 打赏
  • 举报
回复
引用 9 楼 u010401287 的回复:
不是这个意思,有代码上面我列出来了
其实还是这个意思. 比如fun1()需要用到p1和p2 fun2()需要用到p1 fun3()需要用到p2 那么如果需要对输入的参数进行控制,比如范围必须在1-100之间之类的 就不需要在fun1(),fun2(),fun3()里分别判断许多次,而只在set里判断一次就足够了
於黾 2014-09-22
  • 打赏
  • 举报
回复
比如最简单的应用: 自定义一个textbox控件 那么你要把它的text属性赋值为null,是绝对不允许的行为 而且赋值之后,显示的文字要刷新,那么赋值之后就要立即执行刷新的方法,而不是又在外部手动去刷新 如果赋值跟它现在的值相同,则不必多余的去执行一遍刷新的方法 还有,textbox有位置,高度,宽度的属性,还有range属性(所在的区域),位置和宽高确定了,range也就确定了,range必须是只读的,不能另外改成别的东西 这些就是声明为属性的好处,比直接定义成public的变量直接修改要好的多
蹦极的馒头 2014-09-22
  • 打赏
  • 举报
回复
引用 7 楼 Z65443344 的回复:
不就是 public Int i1; 和 public Int I1{get;set} pravit int i1; 的区别吗 设计成属性,就可以用get和set方法来校验输入的值,确保不会在类的外部把全局变量赋值成一个非法的数字 而且有些变量必须是只读的,不允许在外部修改的
不是这个意思,有代码上面我列出来了
蹦极的馒头 2014-09-22
  • 打赏
  • 举报
回复
这是代码: 方式1(传统方式) 调用方: ClassTest test=new ClassTest(); test.fun1(string param1,int param2); 方法实现类(Class ClassTest): public void fun1(string param1,int param2) { // do something... } 方式2(参数通过属性) 调用方: ClassTest test=new ClassTest(); test.Param1="aaa"; test.Param2=2; test.fun1(); 方法实现类(Class ClassTest): public class ClassTest { public string Param1{get;set;} public string Param2{get;set;} public void fun1() { // do something used Param1 and Param2 } }
於黾 2014-09-22
  • 打赏
  • 举报
回复
不就是 public Int i1; 和 public Int I1{get;set} pravit int i1; 的区别吗 设计成属性,就可以用get和set方法来校验输入的值,确保不会在类的外部把全局变量赋值成一个非法的数字 而且有些变量必须是只读的,不允许在外部修改的
蹦极的馒头 2014-09-22
  • 打赏
  • 举报
回复
引用 1 楼 caozhy 的回复:
不知道你说的两种方式是什么和什么,你应该给出代码。 可以确定的一点是,这是设计层面的事情,无所谓优劣,也没有性能问题。
方式1(传统方式) 调用方: ClassTest test=new ClassTest(); test.fun1(string param1,int param2); 方法实现类(Class ClassTest): public void fun1(string param1,int param2) { // do something... } 方式2(参数通过属性) 调用方: ClassTest test=new ClassTest(); test.Param1="aaa"; test.Param2=2; test.fun1(); 方法实现类(Class ClassTest): public class ClassTest { public string Param1{get;set;} public string Param2{get;set;} public void fun1() { // do something used Param1 and Param2 } }
threenewbee 2014-09-21
  • 打赏
  • 举报
回复
不知道你说的两种方式是什么和什么,你应该给出代码。 可以确定的一点是,这是设计层面的事情,无所谓优劣,也没有性能问题。

111,100

社区成员

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

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

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