1

Consider the following situation which results in:

The type 'ConnectionStringSettingsCollection' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Configuration, Version ...'.

Assembly A.dll:

// References System.Configuration

public class Foo
{
    public Foo(int value)
    {
        // ...
    }

    // ConnectionStringSettingsCollection is defined in System.Configuration
    public Foo(ConnectionStringSettingsCollection connString)  
    { 
        // ...
    }
}

Assembly B.dll:

// References A.dll and _not_ System.Configuration

public class Bar
{
    void SomeMethod()
    {
        var aFoo = new Foo(3); // Complains
    }
}

The line var aFoo = new Foo(3); complains with the error message mentioned above, which is clear and understandable.

However I don't understand, why I have to reference System.Configuration in assembly B.dll when the type isn't publicly exposing any property nor has any method which returns anything of that type.

rene
  • 41,474
  • 78
  • 114
  • 152
Matthias Güntert
  • 4,013
  • 6
  • 41
  • 89
  • have you added the corresponding using statement? – Iria Jan 10 '20 at 10:18
  • Does this answer your question? [The type is defined in an assembly that is not referenced, how to find the cause?](https://stackoverflow.com/questions/20660999/the-type-is-defined-in-an-assembly-that-is-not-referenced-how-to-find-the-cause) – nalka Jan 10 '20 at 10:18
  • 5
    The C# compiler needs to decide which particular constructor overload is most appropriate. It insists on knowing everything about them, can't do that when it doesn't know what a ConnectionStringSettingsCollection might be. You could consider whether that constructor should be internal or a factory method is more appropriate. – Hans Passant Jan 10 '20 at 10:19
  • Thanks Hans, that answers my question. – Matthias Güntert Jan 10 '20 at 10:27

1 Answers1

4

the type isn't publicly exposing any property nor has any method which returns anything of that type

This is not really true. The Foo type has a public constructor which expects that type as its argument:

public Foo(ConnectionStringSettingsCollection connString) 

hence it is part of the type's (and the assembly's) public contract. In the B assembly the compiler needs to understand this contract in full, so that it is able to resolve and call the right methods, properties, constructors etc.

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
  • Calling new Foo(3) isn't allowed but calling new Foo(value: 3) is. The compiler can easily infer that 3 is of type int whether named arguments are used or not. There must be another reason. – Jess Rod May 17 '22 at 09:23
  • @JessRod No, it cannot _that_ easily. Custom implicit conversion operators may come into play. When the explicit argument name `value` is used, it disambiguates the situation. – Ondrej Tucny May 24 '22 at 17:44