有没有类似于C#中构造函数的explicit关键字的东西?它似乎只影响 C# 中的强制转换运算符。
举这个例子:
public Foo( long value )
{
m_value = value;
}
我正在寻找的是一种使以下代码无法编译的方法:
int bar = 10;
Foo fail = new Foo( bar );
这在 C# 中可能吗?
您可以通过添加采用
int
的构造函数的重载来导致编译器错误,并将其标记为已过时:
public class Foo {
private long m_value;
public Foo(long value) {
m_value = value;
}
[Obsolete("The constructor has to be called with a long value, not an int value.", true)]
public Foo(int value) {}
}
通过指定
true
作为 Obsolete
的第二个参数,它将导致编译器错误而不是通常的警告。
C# 不提供与 C++
explicit
关键字等效的功能。
但是,您可以创建自己的 Long
类,在其中仅启用您想要的转换(因此这里,不要定义 int
的隐式转换运算符)。
public class MyLong
{
public long Value { get; set; }
// Declare here any wanted conversion operator
}
然后:
public Foo( MyLong mylong )
{
m_value = mylong.Value;
}
如果使用整数调用,将无法编译。
据我所知,恐怕 C# 中没有与 C++ 中构造函数参数上使用
explicit
等效的东西,没有任何东西会按照您想要的方式导致编译器错误。正如您所注意到的, explicit
关键字仅适用于强制转换运算符。
int
可以隐式转换为 long
而不会损失精度,所以确实如此。在这种情况下,我看不出限制类型有任何好处。
实现此目的的一种(非常晦涩的)方法是使用
int
进行重载,并对其应用 Obsolete
属性,并为 true
属性传递 IsError
。
public Foo(long value)
{
m_value = value;
}
[Obsolete("Do not call this with ints", true)]
public Foo(int value)
{
throw new NotImplementedException();
}
使用方法
var x = new Foo(5); // gets error
var x = new Foo(5L); // no warning / error
但是,正如评论中所解释的,这可能是一个糟糕的解决方案,可以用更好的方法来解决。
我回答这个问题只是为了迂腐地按照要求回答问题。
我知道这是非常旧的,但这是我在寻找相同答案时遇到的排名靠前的搜索结果,所以我想我应该添加我的解决方案 - 添加 (或 ref,这在 2014 年可能不可用)到参数:
public class Program
{
public class DataSource
{
public int mInt;
public long mLong;
}
public class LongOnlyIn
{
public LongOnlyIn(in long pLong) { }
}
public class LongOnlyRef
{
public LongOnlyRef(ref long pLong) { }
}
public static void Main()
{
DataSource ds = new DataSource();
LongOnlyIn a = new LongOnlyIn(in ds.mInt); // Error: can't convert from "in int" to "in long"
LongOnlyRef b = new LongOnlyRef(ref ds.mInt); // Error: can't covnert from "ref int" to "ref long"
LongOnlyIn c = new LongOnlyIn(in ds.mLong); // Success!
LongOnlyRef d = new LongOnlyRef(ref ds.mLong); // Success!
}
}
让构造函数签名为 object 而不是 long,然后使用 typeof 来查看该对象是否显式为 long。