使用对象初始化程序,是否可以选择包含属性设置?
例如:
Request request = new Request
{
Property1 = something1,
if(something)
Property2 = someting2,
Property3 = something3
};
Run Code Online (Sandbox Code Playgroud) C#不允许实例字段初始值设定项引用另一个字段.例如,此代码无效:
class A
{
string s1 = "";
string s2 = s1;
}
Run Code Online (Sandbox Code Playgroud)
因为"s2"引用"s1".
但为什么不允许这样做呢?
我的第一个想法是C#规范不保证任何初始化顺序,但根据规范,顺序是声明的顺序:
变量初始值设定项以它们出现在类声明中的文本顺序执行.
因此,如果订单是确定性的,那么这类代码的缺陷可能是什么?
在此先感谢您的帮助.
编辑:
根据Hps,0xA3和Peter的答案:
继承方案中的初始化顺序可能非常混乱,
实现这样的功能需要编译器开发团队的一些资源,但收效甚微,
由于逻辑原因,不可能使用方法或属性(感谢Peter),因此为了保持一致性,字段也是如此.
假设我有一个具有字典<string,bool>属性的类,使用对象初始化程序我可以使用这种语法(我觉得看起来很干净):
new MyClass()
{
Table = { {"test",true},{"test",false} }
}
Run Code Online (Sandbox Code Playgroud)
但是,在初始化程序之外我不能这样做:
this.Table = { {"test",true},{"test",false} };
Run Code Online (Sandbox Code Playgroud)
为什么初始化器是特例?我猜测它与LINQ要求,协方差或诸如此类的东西有关,但感觉有点不一致,无法在任何地方使用这种初始化器...
C#中的属性可以与集合初始值设定项一起使用吗?
例如,我想做类似以下的事情:
[DictionaryAttribute(){{"Key", "Value"}, {"Key", "Value"}}]
public class Foo { ... }
Run Code Online (Sandbox Code Playgroud)
我知道属性可以有命名参数,因为这看起来与对象初始化器非常相似,我想知道集合初始化器是否也可用.
c# attributes custom-attributes object-initializers collection-initializer
当从拥有 auto 属性的类中调用初始化器时,为什么可以使用对象初始化器来设置私有 set auto 属性?我以两个类为例。
public class MyClass
{
public string myName { get; private set; }
public string myId { get; set; }
public static MyClass GetSampleObject()
{
MyClass mc = new MyClass
{
myName = "Whatever", // <- works
myId = "1234"
};
return mc;
}
}
public class MyOtherClass
{
public static MyClass GetSampleObject()
{
MyClass mc = new MyClass
{
myName = "Whatever", // <- fails
myId = "1234"
};
return mc;
}
}
Run Code Online (Sandbox Code Playgroud) .net c# initialization automatic-properties object-initializers
假设我在javascript中定义了以下内容:
com.company.long.namespace = {
actions: {
add: {
defaults: {
url: 'myurl/submit',
},
invoke: function () {
var submitUrl = this.defaults.url;
com.company.long.namespace.foo.util.server.submit({
url: submitUrl,
success: function() { }
});
},
}
}
};
Run Code Online (Sandbox Code Playgroud)
然后我在JQuery click事件的上下文中调用它:
$(myElem).click(function() {
com.company.long.namespace.actions.add.invoke();
});
Run Code Online (Sandbox Code Playgroud)
由于'this'在jQuery事件回调中的作用方式,因此从此上下文调用时,this.defaults是未定义的.无论如何仍然在这个范围内使用'this',而不必定义完整的命名空间,或者不使用jQuery.proxy?
当我使用 Resharper 重构我的代码以使用对象初始值设定项时,它正确地重新格式化代码,如下代码
var response = new Response();
response.Value = "My value";
Run Code Online (Sandbox Code Playgroud)
变成
var response = new Response
{
Value = "My value",
};
Run Code Online (Sandbox Code Playgroud)
我在 Resharper 选项中找不到任何地方可以将它设置为保留括号作为构造函数代码的一部分(为了一致性,我更喜欢它)。是否可以?我希望 Resharper 将其格式化为:
var response = new Response()
{
Value = "My value",
};
Run Code Online (Sandbox Code Playgroud) 在下面的两个示例代码中,我试图通过使用 C# 普通方法和对象初始值设定项来实例化一个名为Test的类。
DateTime? nullDate = null; //this value will come from somewhere else
DateTime? notNullDate = DateTime.Now;
var test = new Test();
test.Date = nullDate.Value; //exception will throw here
test.Name = "String";
test.AnotherDate = notNullDate.Value;
Run Code Online (Sandbox Code Playgroud)
在上面的示例代码中,我可以清楚地了解调试时哪个属性显示异常。
DateTime? nullDate = null; //this value will come from somewhere else
DateTime? notNullDate = DateTime.Now;
var test = new Test
{
Date = nullDate.Value,
Name = "String",
AnotherDate = notNullDate.Value
};
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,当我使用对象初始值设定项时,我无法理解抛出异常的属性。在这里,我无法逐行调试。如果我初始化了很多属性,则很难识别。
这是我的问题:如何从异常窗口识别哪个属性显示异常?现在内部异常为空。
我通过以这种方式初始化字段来创建对象:
class Example
{
public int a;
public int b;
}
var obj = new Example
{
a = stream.ReadInt(),
b = stream.ReadInt()
};
Run Code Online (Sandbox Code Playgroud)
是否总是在字段“b”之前初始化字段“a”?否则,当以不同的顺序减去流中的值时,可能会出现令人不快的错误。谢谢!
UPD:在评论中,许多人不明白我的意思。我会澄清这个问题。这些记录在不同(.NET、Mono 等)编译器上的行为是否始终相同?
第一的:
var obj = new Example
{
a = stream.ReadInt(),
b = stream.ReadInt()
};
Run Code Online (Sandbox Code Playgroud)
第二:
var a = stream.ReadInt();
var b = stream.ReadInt();
var obj = new Example
{
a = a,
b = b
};
Run Code Online (Sandbox Code Playgroud) C#5.0语言规范7.6.10.2 对象初始化器声明
在等号后面指定对象初始值设定项的成员初始值设定项是嵌套对象初始值设定项,即嵌入对象的初始化.而不是为字段或属性分配新值,嵌套对象初始值设定项中的赋值被视为对字段或属性成员的赋值.嵌套对象初始值设定项不能应用于具有值类型的属性,也不能应用于具有值类型的 只读字段.
虽然我理解在构造函数运行后初始化程序无法修改只读字段,但我没有关于属性限制的线索.
以下是我用于测试此属性限制的代码示例:
using System;
namespace ObjectCollectionInitializerExample
{
struct MemberStruct
{
public int field1;
public double field2;
}
class ContainingClass
{
int field;
MemberStruct ms;
public int Field
{
get { return field; }
set { field = value; }
}
public MemberStruct MS
{
get { return ms; }
set { ms = value; }
}
}
class Program
{
static void Main(string[] args)
{
// Nested object initializer applied to a …Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×2
attributes ×1
closures ×1
exception ×1
field ×1
javascript ×1
jquery ×1
resharper ×1