TheChemist
TheChemist

Reputation: 357

Is there a way to force explicit parameter types in a constructor?

Is there anything similar to the explicit keyword for constructors in C#? It only seems to affect the cast operators in C#.

Take this example:

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

What I'm looking for is a way to make the following code fail to compile:

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

Is this possible in C#?

Upvotes: 1

Views: 1041

Answers (6)

user3610013
user3610013

Reputation: 51

I know this is super old but this was a high-ranked search result that I came across while looking for the same answer so I thought I'd add my solution - add in (or ref, which may not have been available in 2014) to the parameters:

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

Upvotes: 0

Chris Mantle
Chris Mantle

Reputation: 6683

As far as I know, I'm afraid that there isn't any equivalent in C# to the use of explicit on constructor parameters in C++, nothing that will cause a compiler error in the way that you want. As you note, the explicit keyword is only for use with cast operators.

int can be implicitly casted to long with no loss of precision, so it will be. I can't see any advantage to restricting the type in this instance.

Upvotes: 3

Matthew
Matthew

Reputation: 25743

One (really obscure) way of accomplishing this is to have an overload taking an int and have the Obsolete attribute applied to it, and pass true for the IsError property.

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

[Obsolete("Do not call this with ints", true)]
public Foo(int value)
{
    throw new NotImplementedException();
}

Usage

var x = new Foo(5); // gets error

var x = new Foo(5L); // no warning / error

However, as explained in the comments, this is probably a bad solution to a problem that could be solved a much better way.

I only answered this question to be pedantic about answering the question as requested.

Upvotes: 1

Guffa
Guffa

Reputation: 700152

You can cause a compiler error by adding an overload of the constructor that takes an int, and mark it as obsolete:

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) {}

}

By specifying true as the second parameter for Obsolete it will cause a compiler error instead of the usual warning.

Upvotes: 15

quantdev
quantdev

Reputation: 23793

C# offers no equivalent to the C++ explicit keyword. However you can create your own Long class where you enable only the conversions that you want (so here, do not define an implicit conversion operator to int).

public class MyLong
{
    public long Value { get; set; }

    // Declare here any wanted conversion operator
}

and then:

public Foo( MyLong mylong )
{
    m_value = mylong.Value;
}

This will fail to compile if called with an integer.

Upvotes: 4

Rick Davin
Rick Davin

Reputation: 1041

Have the constructor signature be for object instead of long, and then use typeof to see if the object was explicitly long.

Upvotes: -7

Related Questions