当我在调查Javascript代码中的词法闭包问题时,我在Python中遇到了这个问题:
flist = []
for i in xrange(3):
def func(x): return x * i
flist.append(func)
for f in flist:
print f(2)
Run Code Online (Sandbox Code Playgroud)
请注意,此示例谨慎避免lambda
.它打印"4 4 4",这是令人惊讶的.我期待"0 2 4".
这个等效的Perl代码是正确的:
my @flist = ();
foreach my $i (0 .. 2)
{
push(@flist, sub {$i * $_[0]});
}
foreach my $f (@flist)
{
print $f->(2), "\n";
}
Run Code Online (Sandbox Code Playgroud)
打印"0 2 4".
你能解释一下这个区别吗?
更新:
这个问题是不是与i
是全球性的.这显示相同的行为:
flist = []
def outer():
for i in xrange(3):
def inner(x): return x * i …
Run Code Online (Sandbox Code Playgroud) 当我在C#中发生早期/晚期绑定时,我正试图解决这个问题.
非虚方法总是早期绑定.虚方法总是后期绑定:编译器插入额外的代码来解析在执行时绑定到的实际方法并检查类型安全性.因此,子类型多态性使用后期绑定.
使用反射调用方法是后期绑定的一个示例.我们编写代码来实现这一点,而不是编译器.(例如,调用COM组件.)
当Option Strict关闭时,VB.NET支持隐式后期绑定.当对象被赋值为声明为Object类型的变量时,该对象是后期绑定的.VB编译器在执行时插入代码以绑定到正确的方法并捕获无效的调用.C#不支持此功能.
我正朝着正确的方向前进吗?
如何调用委托并通过接口引用调用方法?是早期还是晚期绑定?
我可以为System.Object
(所有)的所有子类创建一个Extension方法吗?
例:
<Extension>
Public Function MyExtension(value As Object) As Object
Return value
End Function
Run Code Online (Sandbox Code Playgroud)
以上函数不适用于对象实例:
Dim myObj1 As New Object()
Dim myObj2 = myObj1.MyExtension()
Run Code Online (Sandbox Code Playgroud)
编译器不接受它,是我电脑中的问题?:)
更新
问题似乎只发生在VB中,其中对象的成员通过反射(后期绑定)查找.
在回答
FYI 之后更新,因为vb具有C#缺少的优点,导入模块的成员被导入到全局范围,因此您仍然可以在没有包装器的情况下使用此函数:
Dim myObj2 = MyExtension(myObj1)
Run Code Online (Sandbox Code Playgroud) 我的问题是:C#nativly支持后期绑定IDispatch吗?
假装我正在尝试自动化Office,同时兼容客户安装的任何版本.
在.NET世界中,如果您安装了Office 2000,那么从现在到结束,每个开发人员和每个客户都需要拥有Office 2000.
在.NET之前的世界中,我们使用COM与Office应用程序进行通信.
例如:
1)使用版本独立的ProgID
"Excel.Application"
Run Code Online (Sandbox Code Playgroud)
解析为:
clsid = {00024500-0000-0000-C000-000000000046}
Run Code Online (Sandbox Code Playgroud)
然后使用COM,我们要求将其中一个类实例化为一个对象:
IUnknown unk;
CoCreateInstance(
clsid,
null,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IUnknown,
out unk);
Run Code Online (Sandbox Code Playgroud)
现在我们即将参加比赛 - 能够在我的应用程序中使用Excel.当然,如果你真的想要使用该对象,你必须调用一些方法来调用方法.
我们可以得到阿霍德不同的接口声明,翻译成我们的语言.这项技术很好,因为我们得到了
一些示例代码可能是:
Application xl = (IExcelApplication)unk;
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
Worksheet worksheet = workbook.ActiveSheet;
Run Code Online (Sandbox Code Playgroud)
但是使用接口有一个缺点:我们必须得到各种接口声明,转换成我们的语言.我们坚持使用基于方法的调用,必须指定所有参数,例如:
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
xl.Worksheets.Add(before, after, count, type, lcid);
Run Code Online (Sandbox Code Playgroud)
在现实世界中,这证明了我们愿意放弃的这些缺点:
而是使用IDispatch后期绑定:
Variant xl = (IDispatch)unk;
Variant …
Run Code Online (Sandbox Code Playgroud) 我有一个文本框和RichTextBox的事件处理程序.代码完全相同,但是
在处理程序#1中我做:
RichTextBox tb = (RichTextBox)sender
Run Code Online (Sandbox Code Playgroud)
因此在处理程序#2中:
TextBox tb = (TextBox)sender
Run Code Online (Sandbox Code Playgroud)
这样做我可以完全操纵发送控件.我想知道的是如何使用发送对象根据其类型将发送对象强制转换为Textbox或RichTextbox
sender.GetType().Name
Run Code Online (Sandbox Code Playgroud)
然后在运行时创建控件并使用它.这样我只需要一个事件处理函数:更少的代码,更少的错误,更容易维护和干:-)
我正在准备一个Visual Basic 2005上的一个类,目标是Visual Basic 6程序员迁移到.NET平台.
我想就是否建议他们始终启用Option Strict提出建议.
我专门使用C风格的编程语言,主要是Java和C#,所以对我来说,显式的转换是我一直希望我必须做的事情,因为它从来都不是一个选择.
但是我认识到使用内置支持后期绑定的语言的价值,因为不必过分明确代码中的类型确实可以节省时间.动态类型语言的流行扩散进一步证明了这一点即使在具有动态语言运行时的.NET平台上也是如此.
考虑到这一点,如果第一次使用VB.NET和VB6背景接近.NET的人应该被鼓励进入必须使用编译时类型检查的思维模式,因为这是"最佳实践". CLR?或者继续享受后期约束的好处是"还可以"吗?
在讨论计算机语言的演变时,Alan Kay说他的Smalltalk最重要的一个属性是后期绑定; 它赋予语言可塑性和可扩展性,并允许不适当的耦合随着时间的推移被重构.你同意吗?是否有早期约束的补偿优势可以解释为什么它似乎是两个范式的主导,哪个域可以使用?
基于使用javascript,jQuery,jsext,actionscript,php,java,RoR和asp.net实现Web应用程序的个人经验(不是广泛或深度不具有权威性)似乎暗示了后期绑定和膨胀之间的正相关减少.早期绑定我肯定有助于检测和防止某些类型的安全错误,但自动完成和良好的IDE以及一般的良好编程实践也是如此.因此,在我的风险规避方面恢复我的理性观点之前,我倾向于抓住自己为后期约束方而生根.
但我对如何平衡权衡并没有很好的理解.
我将举一个使用System.Data.SQLite.DLL的例子, 它是一个带有非托管代码的混合程序集:如果我执行这个:
var assembly= Assembly.LoadFrom("System.Data.SQLite.DLL")
Run Code Online (Sandbox Code Playgroud)
没有异常被抛出,但如果我这样做:
var rawAssembly = File.ReadAllBytes("System.Data.SQLite.DLL");
var assembly = Assembly.Load(rawAssembly);
Run Code Online (Sandbox Code Playgroud)
CLR抛出FileLoadException,其中包含"无法验证的代码失败的策略检查.(HRESULT异常:0x80131402)".假设我正在尝试在子AppDomain上加载此程序集,如何自定义AppDomain的安全性以允许我通过策略检查?
如果我在PHP中有一个实例,那么获取该实例的静态属性('类变量')的最简单方法是什么?
这个
$classvars=get_class_vars(get_class($thing));
$property=$classvars['property'];
Run Code Online (Sandbox Code Playgroud)
声音真的太过分了.我期待
$thing::property
Run Code Online (Sandbox Code Playgroud)
要么
$thing->property
Run Code Online (Sandbox Code Playgroud)