静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作.在创建第一个实例或引用任何静态成员之前自动调用它.
最后一部分(关于何时被自动调用)让我陷入了一个循环; 直到阅读那部分我认为通过简单地以任何方式访问一个类,我可以确定它已经调用了它的基类的静态构造函数.测试和检查文档表明情况并非如此; 看起来基本类的静态构造函数不能保证在访问该基类的成员之前运行.
现在,我想在大多数情况下,当您处理派生类时,您将构造一个实例,这将构成正在创建的基类的实例,因此将调用静态构造函数.但是,如果我只处理派生类的静态成员,那么呢?
为了使这更具体一点,我认为下面的代码可以工作:
abstract class TypeBase
{
static TypeBase()
{
Type<int>.Name = "int";
Type<long>.Name = "long";
Type<double>.Name = "double";
}
}
class Type<T> : TypeBase
{
public static string Name { get; internal set; }
}
class Program
{
Console.WriteLine(Type<int>.Name);
}
Run Code Online (Sandbox Code Playgroud)
我假设访问Type<T>该类会自动调用静态构造函数TypeBase; 但事实并非如此.Type<int>.Name是null,并且上面的代码输出空字符串.
除了创建一些虚拟成员(就像Initialize()什么都不做的静态方法)之外,还有更好的方法来确保在使用任何派生类型之前调用基类型的静态构造函数吗?
如果没有,那么......虚拟成员就是!
关于接受的答案的快速说明:我不同意Jeffrey的一小部分答案,即Delegate必须是一个引用类型,因此所有代表都是引用类型.(多层继承链排除值类型并不是真的;例如,所有枚举类型都System.Enum继承自System.ValueType,而继承自所有引用类型的继承System.Object,但是我认为事实是从根本上说,所有代表事实上都不仅仅是继承而是来自这里的关键实现.正如雷蒙指出,在一个评论他的答案,一旦你承诺支持多用户,有真的没有一点不使用引用类型的代表本身,因为需要一个数组的地方.DelegateMulticastDelegate
请参阅底部的更新.
如果我这样做,我一直觉得很奇怪:
Action foo = obj.Foo;
Run Code Online (Sandbox Code Playgroud)
我每次都在创建一个新 Action对象.我确信成本很低,但它涉及到内存分配以便以后进行垃圾回收.
鉴于委托本身就是不可变的,我想知道为什么它们不能成为价值类型?然后像上面那样的一行代码只会对堆栈上的内存地址进行简单的赋值*.
即使考虑匿名功能,似乎(对我而言)这也行得通.请考虑以下简单示例.
Action foo = () => { obj.Foo(); };
Run Code Online (Sandbox Code Playgroud)
在这种情况下foo确实构成了一个闭包,是的.在许多情况下,我想这确实需要一个实际的引用类型(例如当局部变量被关闭并在闭包内被修改时).但在某些情况下,它不应该.例如,在上面的例子中,似乎支持闭包的类型看起来像这样: 我收回了我对此的原始观点.下面确实需要一个引用类型(或:它并不需要是的,但如果它是一个struct只是要它来获得反正盒装).所以,忽略下面的代码示例.我留下它只是为了提供具体提及它的答案的背景.
struct CompilerGenerated
{
Obj obj;
public CompilerGenerated(Obj obj)
{
this.obj = obj;
}
public void CallFoo()
{
obj.Foo();
}
}
// …Run Code Online (Sandbox Code Playgroud) 我可能只是没有想到这一点,或者我可能根本没有意识到Subversion中已有的选项(我当然不是专家).
我只是想知道,如果我已经创建了一个分支来开始处理一些新功能,如果有一种更容易的方法来保持分支机构与主干的最新版本保持同步而不必经历所有麻烦合并一系列修订.我想能够简单地更新,并从行李箱(所有版本和分支,当然),而我提交的修改只会影响分支.这可能吗?我问的问题有意义吗?
我认为这与合并一系列修订并不一定有所不同; 只是我使用AnkhSVN,它在允许合并之前执行所有这些最佳实践检查,有时感觉它比它需要的复杂得多.这个想法是,我要保持我的分支上最新与任何提交其他开发商可能使躯干,这样,当我最终做我的分支合并到主干,一切顺利(AS)顺利(尽可能).
2009-12-04更新:有关在此处发布的一些建议的分析结果,请参阅下文!
考虑以下非常无害,非常简单的方法,它使用switch语句返回定义的枚举值:
public static MarketDataExchange GetMarketDataExchange(string ActivCode) {
if (ActivCode == null) return MarketDataExchange.NONE;
switch (ActivCode) {
case "": return MarketDataExchange.NBBO;
case "A": return MarketDataExchange.AMEX;
case "B": return MarketDataExchange.BSE;
case "BT": return MarketDataExchange.BATS;
case "C": return MarketDataExchange.NSE;
case "MW": return MarketDataExchange.CHX;
case "N": return MarketDataExchange.NYSE;
case "PA": return MarketDataExchange.ARCA;
case "Q": return MarketDataExchange.NASDAQ;
case "QD": return MarketDataExchange.NASDAQ_ADF;
case "W": return MarketDataExchange.CBOE;
case "X": return MarketDataExchange.PHLX;
case "Y": return MarketDataExchange.DIRECTEDGE;
}
return MarketDataExchange.NONE;
}
Run Code Online (Sandbox Code Playgroud)
我和我的同事今天就如何更快地实现这个方法的几个想法进行了斗争,并且我们想出了一些有趣的修改,实际上相当显着地提高了它的性能(当然,按比例说).我有兴趣知道那里的其他人可以想到哪种优化可能没有发生在我们身上.
接下来,让我简单地提供一个快速免责声明:这是为了好玩 …
我今天早些时候发生的事情让我摸不着头脑.
Nullable<T>可以为任何类型的变量赋值null.例如:
int? i = null;
Run Code Online (Sandbox Code Playgroud)
起初,我看不出如何做到这一点是可能的,而不以某种方式从定义的隐式转换object到Nullable<T>:
public static implicit operator Nullable<T>(object box);
Run Code Online (Sandbox Code Playgroud)
但是上面的运算符显然不存在,就好像它确实如此,那么下面的内容也必须是合法的,至少在编译时(它不是):
int? i = new object();
Run Code Online (Sandbox Code Playgroud)
然后我意识到,也许Nullable<T>类型可以定义一个隐式转换为一些永远无法实例化的任意引用类型,如下所示:
public abstract class DummyBox
{
private DummyBox()
{ }
}
public struct Nullable<T> where T : struct
{
public static implicit operator Nullable<T>(DummyBox box)
{
if (box == null)
{
return new Nullable<T>();
}
// This should never be possible, as a DummyBox cannot be instantiated.
throw new InvalidCastException();
}
} …Run Code Online (Sandbox Code Playgroud) 我意识到一个可调整大小的索引集合,它使用一个数组来存储它的元素(比如List<T>在.NET或ArrayListJava中),在集合的末尾分配了O(1)插入时间.但是在关键接合点处总是有一个令人讨厌的插入,其中集合刚刚达到其容量,并且下一次插入需要将内部阵列中的所有元素的完整副本转换为新的元素(可能是两倍大).
一个常见的错误(在我看来)是使用链表来"修复"这个问题; 但我相信为每个元素分配一个节点的开销可能非常浪费,事实上,在极少数情况下阵列插入成本很高的情况下,保证O(1)插入的好处相形见绌 - 事实上,其他每一个阵列插入明显更便宜(也更快).
我认为可能有意义的是一种混合方法,它由一个链接的数组列表组成,每当当前的"head"数组达到其容量时,一个两倍大的新数组被添加到链表中.然后,由于链表仍然具有原始数组,因此不需要复制.从本质上讲,这似乎与我相似(List<T>或者说是ArrayList方法),除了以前你曾经承担过复制内部数组所有元素的成本,这里你只需要分配新数组和单个节点插入的成本.
当然,如果需要它们会使其他特征复杂化(例如,插入/移出集合的中间); 但正如我在标题中所表达的那样,我真的只是在寻找一个只添加(和迭代)的集合.
是否有适合此目的的数据结构?或者,你能想到一个吗?
我接受了MUG4N对这个问题的回答,我也想回应一些针对它提出的批评.
克里斯夫说:
...您无法直接从后台线程进行UI调用.
这是一个一揽子声明,并非100%正确.我只想指出一些事实:
实际上,你可以使UI呼吁所有你想要的,如果你设置Control.CheckForIllegalCrossThreadCalls = false."确认!" 我听你说."不要永远做!" 是的,是的 - 但为什么呢?答案:因为有时这会破坏记忆.
中的控件类System.Windows.Forms不是编写为线程安全的,因此有时从后台线程更新它们可能会破坏内存.但是,如果这种情况有时只发生而且并非总是如此,那么这告诉我的不是UI代码本身的调用,而是可能导致异常的UI代码的潜在不安全冲突.
为了强调第1点,请考虑以下事项:从后台线程调用UI代码的"安全"方法是使用Control.Invokeor Control.BeginInvoke,对吗?但这是一个UI调用 ; 如果我们从非GUI线程更新GUI,那只是我们应该进行的 UI调用.我的意思是,显然,它不是简单地Control从外部线程调用对象的"任何"方法,这将导致混乱(如果是这种情况,那么我们甚至无法调用Invoke,我们将被完全卡住) .同样,它是单独的UI调用的潜在冲突,它们不能同时安全地发生,这将证明具有破坏性.
牢记以上两点,请问自己:为什么MessageBox.Show从非GUI线程调用会不安全?Form创建并显示完全独立的内容; 它的属性不以任何方式与任何其他现有GUI对象交互; 事实上,它不能以任何方式在任何地方访问,除了一个:来自调用线程,它访问其属性(并且只通过方法的返回值).DialogResultShow
继续前进.康拉德·阿尔布雷希特说:
...鉴于断言Show()在Dan的ref'd主题中设置了自己的消息泵,(这没有证实,但我不能反驳)......
这是一个完全公平的观点(尽管我个人非常尊重贾里德帕尔,我通常不会怀疑他说的是什么).无论如何,MessageBox.Show通过Reflector查看方法会显示以下片段:
Application.BeginModalMessageLoop();
try
{
result …Run Code Online (Sandbox Code Playgroud) 这是一个纯粹迂腐的问题,以满足自己的好奇心.
我倾向于在问题中使用后一种选择(所以if (boolCheck) { ... }:),而同事总是写前者(if (boolCheck == true) { ... }).我总是有点嘲笑他,并且从他第一次开始编程时他总是把它解释为一种旧习惯.
但是我今天刚刚想到,实际写出整个== true部分可能实际上需要一个额外的处理步骤,因为任何带有==运算符的表达式都会被计算为布尔值.这是真的?
换句话说,据我所知,没有 == true行的选项可以松散地描述如下:
使用 == true行的选项更像是:
我对么?或者也许任何普通的编译器/解释器都会消除这种差异?或者我忽略了什么,而且根本没有什么区别?
显然,在实际观察到的性能方面没有区别.就像我说的,我只是好奇.
编辑:感谢所有实际发布编译结果的人,以说明两种方法之间的步骤是否不同.(看起来,大部分时间,它们都是,虽然只是轻微的.)
我只想重申,我并不是在问什么是"正确的"方法.我知道很多人喜欢一个人而不是另一个人.我也理解,从逻辑上讲,两者是相同的.如果CPU执行的实际操作对于两种方法完全相同,我只是很好奇; 事实证明,在很多时候(显然它取决于语言,编译器等),它们不是.
伙计们,请原谅我.对于Ruby来说,我充其量只是一个新手.我只是想知道对我来说看起来很奇怪的行为的解释.
我正在使用Savon库与我的Ruby应用程序中的SOAP服务进行交互.我注意到以下代码(在我编写的用于处理此交互的类中)似乎传递空值,我希望成员字段的值可以去:
create_session_response = client.request "createSession" do
soap.body = {
:user => @user, # This ends up being empty in the SOAP request,
:pass => @pass # as does this.
}
end
Run Code Online (Sandbox Code Playgroud)
尽管这是一个事实,即@user与@pass已初始化为非空字符串.
当我更改代码以使用本地代码时,它的工作方式与我期望的一样:
user = @user
pass = @pass
create_session_response = client.request "createSession" do
soap.body = {
:user => user, # Now this has the value I expect in the SOAP request,
:pass => pass # and this does …Run Code Online (Sandbox Code Playgroud) 显然TaskFactory.StartNew,.NET 4.0中的方法旨在替代ThreadPool.QueueUserWorkItem(根据这篇文章,无论如何).我的问题很简单:有谁知道为什么?
是否TaskFactory.StartNew有更好的表现?它使用更少的内存吗?或者它主要是为了Task班级提供的附加功能?在后一种情况下,StartNew可能会有比较差的表现QueueUserWorkItem吗?
在我看来,StartNew实际上可能会使用更多的内存QueueUserWorkItem,因为它会Task在每次调用时返回一个对象,我希望这会导致更多的内存分配.
无论如何,我很想知道哪种更适合高性能场景.
.net ×5
c# ×4
optimization ×2
performance ×2
ankhsvn ×1
arrays ×1
big-o ×1
block ×1
blocking ×1
boolean ×1
boxing ×1
branch ×1
delegates ×1
inheritance ×1
merge ×1
messagebox ×1
nonblocking ×1
nullable ×1
ruby ×1
savon ×1
svn ×1
task ×1
taskfactory ×1
threadpool ×1
trunk ×1
value-type ×1
vb.net ×1
winforms ×1