1334

我有两个构造函数,它们将值提供给只读字段。

公共类示例{public Sample(字符串theIntAsString){int i=int.Parse(IntAsString);_intField=i;}公共样本(inttheInt)=>_intField=theInt;public int IntProperty=>_intField;私有只读int _intField;}

一个构造函数直接接收值,另一个构造函数进行一些计算并获取值,然后设置字段。

现在有一个问题:

  1. 我不想复制设置代码。在这种情况下,只有一个字段已设置,但当然可以我们不止一个。
  2. 要使字段只读,我需要从构造函数中设置它们,所以我无法将共享代码“提取”到实用函数。
  3. 我不知道怎么叫另一个构造函数。

有什么主意吗?

0

11答案11

重置为默认值
2100

这样地:

public Sample(string str):this(int.Parse(str)){}
14
  • 72
    @阿维:你可以做一个静止的操作参数的方法。 评论 2010年10月25日11:26
  • 25
    我可以知道这个的执行顺序吗?中的所有内容示例(字符串)将首先执行,然后样本(int)还是先执行int版本,然后再返回字符串版本?(比如打电话super()Java?) 评论 2013年12月18日16:49
  • 30
    @RosdiKasim:基类构造函数总是先运行。您无法使用或查看直到它的基类被初始化。 评论 2013年12月18日16:59
  • 6
    @伊万·波兹迪夫:是的,你可以;使用?:或调用静态方法。 评论 2014年10月12日1:17
  • 5
    @乔治比丽斯:是的。他想在调用另一个ctor之前运行(关于参数的)代码。在这一点上,没有实例。 评论 2015年9月6日1:42
205

如果不使用自己的方法进行初始化,就无法令人满意地实现所需的内容(例如,因为您想在初始化代码之前做太多,或将其包装在try-finally中,或其他),则可以让任何或所有构造函数通过引用初始化例程来传递只读变量,这样就可以随意操作它们。

公共类示例{私有只读int _intField;public int IntProperty=>_intField;private void setupStuff(ref int intField,int newValue)=>intField=newValue;public Sample(字符串theIntAsString){int i=int.Parse(IntAsString);setupStuff(ref_intField,i);}public Sample(int theInt)=>setupStuff(ref_intField,the int);}
10
  • 25
    +1个真正的解决方案。使用基础(…)此(…)我们只能执行非常有限的操作。 评论 2012年9月17日9:32
  • 5
    使用外面的关键字而不是裁判? 评论 2013年9月13日20:24
  • 1
    @JeppeStigNielsen:在这种特殊情况下,如果方法只需要在那里存储一些内容,那么它可能是合适的。另一方面,在调用者将某些内容放入字段并调用可能需要或不需要修改它的方法的情况下,也可以使用相同的方法;使用外面的在示例中可能无法清楚地说明这一点。此外,我通常有点怀疑外面的,因为不能保证具有外面的参数将实际存储任何内容。 评论 2013年9月13日20:35
  • 10
    @nawfal:因为如果变量是只读. 评论 2013年11月10日23:38
  • @约翰·卡彭特:如果只有一个只读字段需要设置,设置它的代码可以调用该方法并使用返回值分配字段,但可以直接用裁判此外,如果重要,通过裁判参数会立即发生,甚至在函数返回之前,而使用函数返回值生成的参数则不会发生。 评论 2016年1月9日17:50
79

在构造函数正文之前,使用以下任一选项:

:base(参数):this(参数)

例子:

公共类人员:用户{public People(int EmpID):基本(EmpID){//在此处添加更多语句。}}
4
  • 20
    不幸的是,如果我需要对构造函数调用之间的参数进行一些操作,则无法工作。
    – 丹尼斯
    评论 2013年7月12日17:01
  • 1
    @丹尼斯你不能把一个构造器挂在中间来达到同样的效果吗?
    – 丹伊姆
    评论 2015年6月5日14:08
  • 6
    @丹尼斯,在调用构造函数之前,你什么都不能做。如果要在初始化对象属性之前执行某些操作,请在构造函数示例以外的方法中移动初始化初始化()。可以从任何构造函数调用此方法。 评论 2016年8月4日7:35
  • 1
    @当您需要调用父构造函数时,AbdullahShoaib不会这样做。 评论 2020年3月19日19:29
16

我正在改进超级猫的答案。我想还可以做到以下几点:

类示例{私有只读int _intField;公共int IntProperty{获取{return _intField;}}void setupStuff(ref int intField,int newValue){//根据必要的初始化变量在这里做一些事情。intField=newValue;}public Sample(字符串theIntAsString,bool?doStuff=true){//一些必要变量的初始化。//==========================================int i=int.Parse(IntAsString);// ................// .......................//==========================================if(!doStuff.HasValue||doStuff.Value==true)setupStuff(ref_intField,i);}public Sample(inttheInt):this(theInt,false)//“false”参数,以避免setupStuff()被调用两次{setupStuff(ref_intField,theInt);}}
4
  • 4
    这可能允许第三方通过调用新样本(str,false).
    – 蒂杰伊
    评论 2013年10月9日9:53
  • 1
    这无法编译。 评论 2016年1月15日3:02
  • 1
    这不是一个好方法;混淆;不必要的复杂。如果使用调用另一个构造函数,然后让该构造函数调用setupStuff(设置填充); 删除最后一个构造函数中对setupStuff的调用。那你就不需要doStuff(道夫)/参数。(一个较小的抱怨是,如果你确实有理由使用doStuff(道夫)参数,使其成为可为null的布尔值没有任何好处布尔?。只需使用布尔此外,蒂杰伊指出,这意味着这是一个致命的缺陷设计。 评论 2018年5月5日11:43
  • 1
    更好的代码可能是:public Sample(字符串theIntAsString):this(int.Parse(theIntAs字符串)){} 公共示例(int theInt){setupStuff(ref_intField,the int);}注意,第一个构造函数调用另一个构造函数,不会呼叫setupStuff(设置填充). 评论 2018年5月5日12:01
10

下面是一个调用另一个构造函数的示例,然后检查它设置的属性。

公共SomeClass(int i){I=I;}公共SomeClass(SomeOtherClass soc):此(soc.J){如果(I==0){I=DoSomethingHere();}}
1
  • 1
    如果您在某些情况下使用默认构造函数毛发,并对其他情况进行小的/特定的更改,那么这可能会更干净。 评论 2014年11月25日23:15
9

是的,你可以在调用库或这个之前调用其他方法!

公共类MyException:异常{public MyException(int number):base(ConvertToString(number)){}私有静态字符串ConvertToString(int number){ return number.toString()}}
1
  • 只是为了得到整体答案——如果构造函数应该初始化任何只读字段,则不能使用方法来实现这一点。
    – 透镜体
    评论 2016年7月12日14:10
8

建造商链接也就是说,当你想在一次调用中调用多个构造函数时,你可以用“Base”表示Is关系,用“This”表示同一个类。

类BaseClass{public BaseClass():此(10){}公共基类(int val){}}课程计划{static void Main(字符串[]参数){新建BaseClass();ReadLine();}}
5

从基类继承类时,可以通过实例化派生类来调用基类构造函数

类别样本{公共int x;公共样本(int值){x=值;}}class der:示例{公共int a;公共int b;public der(int value1,int value2):基数(50){a=值1;b=值2;}}班级跑步{公共静态void Main(string[]args){der obj=新der(10,20);系统。慰问。WriteLine(obj.x);系统。慰问。WriteLine(obj.a);系统。慰问。WriteLine(对象b);}}

的输出示例程序

50 10 20


您还可以使用关键字从另一个构造函数调用构造函数

类别样本{公共int x;公共样本(int值){x=值;}公共样本(样本对象):this(obj.x){}}班级跑步{public static void Main(字符串[]参数){样品s=新样品(20);样本ss=新样本;系统。慰问。WriteLine(ss.x);}}

这个的输出示例程序

20

2

错误处理和代码重用是关键。我在int验证中添加了string,如果需要,还可以添加其他类型。使用更可重用的解决方案解决此问题可以是:

公共类示例{公共示例(对象inputToInt){_intField=对象ToInt(输入ToInt);}public int IntProperty=>_intField;private只读int_intField;}公共静态int对象ToInt(对象inputToInt){开关(输入到Int){案例int inputInt:返回inputInt;断裂;case字符串inputString:if(!int.TryParse(inputString,out int-parsedInt)){抛出新的InvalidParameterException($“无法将输入{inputString}解析为int”);}return parsedInt;违约:抛出新的InvalidParameterException($“构造函数不支持{inputToInt.GetType().Name}”);断裂;}}
1
  • 展示不同的方式并不能回答这个问题。如果有十几个不同的字段和不同的设置方式,又该怎么办?对象到Int那就没用了。 评论 2023年9月5日6:51
1

在我的例子中,我有一个主构造函数,它使用OracleDataReader作为参数,但我想使用不同的查询来创建实例:

我有这个密码:

公共订阅者(OracleDataReader contractReader){this.contract=转换。ToString(contractReader[“contract”]);this.customerGroup=转换。ToString(contractReader[“customerGroup”]);this.subGroup=转换。ToString(contractReader[“customerSubGroup”]);this.pricingPlan=转换。ToString(contractReader[“定价计划”]);this.items=新字典<string,Member>();this.status=0;}

所以我创建了以下构造函数:

公共订阅者(string contract,string customerGroup):this(getSubReader(contract、customerGroup)){ }

以及此方法:

私有静态OracleDataReader getSubReader(string contract,string customerGroup){ cmd订阅服务器。参数[“:contract”]。价值=合同+“%”;cmd订阅服务器。参数[“:customerGroup”]。值=customerGroup+“%”;返回cmdSubscriber。ExecuteReader();}

注意:静态定义的cmdSubscriber在代码的其他地方定义;我的主要构造器已经被简化为这个示例。

1
使用系统;使用系统。林克;使用系统。文本;使用系统。穿线;命名空间测试{课程计划{static void Main(字符串[]参数){客户客户=新客户();客户。打印全名();客户customer1=新客户(“Zoyeb”,“Shaikh”);customer1.PrintFullName();}}公共类客户{字符串名字;字符串_名字;公共客户(string fn,string ln){_firstName=fn;_姓氏=ln;}公共客户():this(“无名字”,“无姓氏”){}public void PrintFullName(){慰问。WriteLine(“全名={0}”,this.firstName+“”+this._lastName);}}}

您的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.