如何解决具有显式调用的C#构造函数歧义-错误CS0012
C#中存在无法解释的歧义,我在其中明确尝试调用构造函数,但编译器认为它是不同的构造函数。我将首先展示我们使用的简短C#体系结构。然后显示一个我创建的小“工作”示例,以及可能的解决方案,但我仍然想理解为什么会发生这种情况。
体系结构:
- 桥接C ++ API的CLR DLL。
- 使用桥接级别的C#API。
- 使用C#API的C#客户端应用程序。
- 请注意,不允许C#客户端使用CLR级别。
我创建的示例
CLR DLL中的类:
#pragma once
#include <string>
using namespace System;
namespace Inner {
public ref class AInner
{
public:
AInner() : _data(new std::wstring(L"")) {}
~AInner() {
delete _data;
}
property String^ Val
{
String^ get()
{
return gcnew String((*_data).data());
}
void set(String^ value) {
System::IntPtr pVal = System::Runtime::InteropServices::Marshal::StringToHGlobalUni(value);
*_data = (const wchar_t*)pVal.ToPointer();
System::Runtime::InteropServices::Marshal::FreeHGlobal(pVal);
}
}
private:
std::wstring* _data;
};
}
在DLL中包装CLR级别的类:
using System;
using Inner;
namespace Outer
{
public class A
{
public A()
{
_inner.Val = String.Empty;
}
public A(string val)
{
init(val);
}
public string Val
{
get
{
return _inner.Val;
}
set
{
_inner.Val = value;
}
}
internal A(AInner inner)
{
_inner = inner;
}
private void init(string Val)
{
_inner = new AInner();
_inner.Val = String.Empty;
}
private AInner _inner;
}
}
请注意,有一个internal
构造函数和一个public
构造函数。
使用C#API DLL的可执行客户端:
using Outer;
namespace OneClient
{
class Program
{
static void Main(string[] args)
{
string myString = "Some String";
A testA = new A(myString);
}
}
}
扭曲故事:
在包装CLR级别的DLL中,外部客户端不应使用所有API,而内部客户端可以使用所有API,因此,通过向'AssemblyInfo中添加[assembly: InternalsVisibleto("OneClient")]
,内部可以暴露给内部客户端。 DLL的cs包装CLR级别。
问题
编译客户端代码时,出现以下错误:
error CS0012: The type 'AInner' is defined in an assembly that is not referenced. You must add a reference to assembly 'InnerOne,Version=1.0.7600.28169,Culture=neutral,PublicKeyToken=null'.
- 我不能使用
InnerOne
,因为不允许客户使用此级别。 - 客户端同时接触
A(string val)
和A(AInner inner)
构造函数。
可能的解决方法:
- 删除
[assembly: InternalsVisibleto("OneClient")]
-由于特定客户端需要使用其他内部类,因此这是不可接受的。 - 将
A(string val)
构造函数更改为A(string val,bool unique=true)
并使用它A testA = new A(myString,true)
-不是一个好的解决方案。 - 使用默认构造函数
A()
并调用testA.Val = myString;
-实际上可以,但是代码很多。 - 将客户端代码从
A testA = new A(myString)
更改为A testA = new A(val:myString);
-这实际上是选择的解决方案。
问题
为什么会出现这种歧义?
这是Microsoft编译器中的错误吗?
解决方法
为什么会出现这种歧义?
由于要满足构造函数的重载分辨率,编译器需要知道所有参数类型是什么,并且不知道AInner
是什么。
为什么不将AInner
版本公开为工厂方法:
static internal A Create(AInner inner)
{
return new A { _inner = inner };
}
,
我看不到任何问题,问题在于我们习惯于以错误/简短的方式来做事情。
正确的答案是:
A testA = new A(val:myString);
此外,您的所有调用(以这种方式是对构造函数/初始化程序的调用,但无论如何都是调用)都应使用参数名称。没有人(甚至我)都写它们,但是...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。