【问题标题】:Why does C# allow constructing an object from an interface in "new Shell32.Shell()"?为什么 C# 允许从“new Shell32.Shell()”中的接口构造对象?
【发布时间】:2019-03-14 11:04:39
【问题描述】:

我知道在 C# 中通常不能创建抽象类或接口的实例。有人可以帮我理解这段代码(它编译时没有任何错误)。

Shell32.Shell shObj = new Shell32.Shell();

Shell32.Shell 是来自“shell32.dll”的接口

我尝试了以下方法,但没有编译:

[CoClass(typeof(ShellClass))]
[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
public interface OtherShell : Shell
{
}
OtherShell shObj = new OtherShell();

更新:

为了让它工作,我只需要添加ComImport 属性并更改co-class(我不能选择Shell32.ShellClass)。

谢谢大家!

【问题讨论】:

  • 它是一个 COM 对象。将 COM DLL 导入项目时会生成一个互操作程序集。其中还有一些其他的魔法——实际的类是“Shell32.ShellClass”。在“新 Shell”代码上使用代码导航将移动到 ShellClass 实现,而不是 Shell 接口,因此还有更多的魔力..
  • 是什么让你觉得它是一个界面?
  • @BuhBuh 查看互操作程序集:“[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")] [CoClass(typeof (ShellClass))] [ComImport] public interface Shell ..”(ShellClass 扩展 Shell)。
  • 简短回答:您是正确的,接口不能被实例化。您偶然发现了一些有助于 COM 类实例化的晦涩语法糖。
  • 无需将问题标记为已解决 - 答案就是这样做的。您可以随时回答自己的问题。

标签: c# interface shell32.dll


【解决方案1】:

除了所有其他信息,这里是如何编译代码。接口的使用只是代码的精妙之处。

IL_000c: newobj       instance void [Interop.Shell32]Shell32.ShellClass::.ctor()

也就是说,它是基于 [CoClass] 属性的从接口“到”类的编译时转换。

每个https://stackoverflow.com/a/1094140/2864740,它显示了一个最小的示例案例:

[除了 CoClassAttribute,您]需要 ComImportAttribute 和 GuidAttribute 才能工作

【讨论】:

  • 这几乎违反了 C# 自己的语言标准,即不能实例化接口...
  • @Adrian 这是一个“神奇的编译器转换”,独角兽和会说话的猫 D:
  • 我明白了,如果它真的是指定的东西就好了。
  • @Adrian 我也想要更好的..关于这种行为的文档:}
【解决方案2】:

如果您在 Visual Studio 中右键单击 Shell32.Shell 并转到定义,您将获得以下接口定义:

using System.Runtime.InteropServices;

namespace Shell32
{
    [CoClass(typeof(ShellClass))]
    [Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
    public interface Shell : IShellDispatch6
    {
    }
}

对 ShellClass 执行相同操作,您将获得在代码中创建的具体类:

Shell32.Shell shObj = new Shell32.Shell();

【讨论】:

  • 我想知道是什么负责“创建”对象(对于正确的实现)以尊重 CoClass 属性..?也就是说,C#/specify 怎么知道这个接口是特殊的,或者属性本身是否足够(魔法发生在什么“级别”)?是否生成了特殊的 MSIL(和/或它与正常的 ctor 调用有何不同);也就是说,选择 ShellClass 是运行时魔术还是编译时魔术?这可能会记录在哪里?
  • CoClassAttribute 在这里讨论stackoverflow.com/questions/6960910/…
  • 这也只是给出了一个高级解释,而不是细节:(如果我们决定.NET 不能实例化接口,那么就必须有某种“特殊机制”,通过这种机制,看起来像接口的实例被“转换”为实际的对象创建。
  • @Adrian Answers 那里仍然说'什么让它工作',没有说 如何 它工作.. :}
  • 获取源代码(全部可用)并挖掘referencesource.microsoft.com/#mscorlib/system/runtime/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 2018-09-10
  • 1970-01-01
  • 2014-11-22
相关资源
最近更新 更多