有没有办法在构造函数中强制显式参数类型?

问题描述 投票:0回答:6

有没有类似于C#中构造函数的explicit关键字的东西?它似乎只影响 C# 中的强制转换运算符。

举这个例子:

public Foo( long value )
{
    m_value = value;
}

我正在寻找的是一种使以下代码无法编译的方法:

int bar = 10;
Foo fail = new Foo( bar );

这在 C# 中可能吗?

c# constructor explicit
6个回答
15
投票

您可以通过添加采用

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
的第二个参数,它将导致编译器错误而不是通常的警告。


4
投票

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;
}

如果使用整数调用,将无法编译。


3
投票

据我所知,恐怕 C# 中没有与 C++ 中构造函数参数上使用

explicit
等效的东西,没有任何东西会按照您想要的方式导致编译器错误。正如您所注意到的,
explicit
关键字仅适用于强制转换运算符。

int
可以隐式转换为
long
而不会损失精度,所以确实如此。在这种情况下,我看不出限制类型有任何好处。


1
投票

实现此目的的一种(非常晦涩的)方法是使用

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

但是,正如评论中所解释的,这可能是一个糟糕的解决方案,可以用更好的方法来解决。

我回答这个问题只是为了迂腐地按照要求回答问题。


0
投票

我知道这是非常旧的,但这是我在寻找相同答案时遇到的排名靠前的搜索结果,所以我想我应该添加我的解决方案 - 添加 (或 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!
    }       
}

-7
投票

让构造函数签名为 object 而不是 long,然后使用 typeof 来查看该对象是否显式为 long。

© www.soinside.com 2019 - 2024. All rights reserved.