Curious dependency resolution error - c#

I've recently encountered a dependecy resolution error that I'm hoping someone here can explain.
I have an interface defined in a 3rdparty assembly (I3rdParty), one "common" assembly that's depends on that assembly and a "client" library that depends on the "common" assembly.
Let's call them, 3rdparty.dll, common.dll and client.dll.
The client.dll should not have a dependency to the 3rdparty.dll.
in common.dll the following was defined:
public static class Factory
{
public static object Create(I3rdParty ifc) { ... }
public static object Create(string value1, string value2, long? value3 = null) { ... }
}
One of the factory methods was used from the client.dll like:
var instance = Factory.Create("SomeValue", "SomeValue2");
At this point everything worked as expected.
Then a bool parameter was introduced to the first factory method in common.dll so it became:
public static object Create(I3rdParty ifc, bool value) { ... }
Then the build of client.dll started failing due to a missing dependency to 3rdparty.dll, e.g:
The type 'I3rdParty' is defined in an assembly that is not referenced...
I'm assuming that this has something to do with that the methods now accepts the same number of parameters (since the second Create method's third parameter defaults to null).
But I thought that it would still be able to select the correct Create method based on the type of the parameters. Can anyone explain the reason for the behavior I'm seeing?

After you added a bool parameter to the first overload, the compiler has now to check for two possible method signatures to choose the one that should be used (this is the overload resolution).
You're calling Create(string, string)
With two parameters, you have the following overloads available:
Create(I3rdParty, bool)
Create(string, string)
Obviously only the second one can match (as a string cannot be implicitly converted to bool for the second parameter), but it appears the compiler is not clever enough and has to know what exactly I3rdParty is (which means it requires the reference to the assembly that defines it), before being able to determine the (I3rdParty, bool) overload wasn't an option.

Related

Two extension methods with same name

I have the following two extension methods (the body of the methods is not particularly important for my question, but including the code anyway)
public static class DictionaryExtensions
{
public static TValue GetValue<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key, TValue defaultValue)
{
return (source.ContainsKey(key) ? source[key] : defaultValue);
}
}
public static class WebExtensions
{
public static T GetValue<T>(this HttpContext context, string name, T defaultValue)
{
object value = context.Request.Form[name] ?? context.Request.QueryString[name];
if (value == null) return defaultValue;
return (T)value;
}
}
These two methods share the same name but they extend two very different types. I would expect the following code to be simple and the compiler to be able to pick the appropriate extension method:
var myDict = new Dictionary<int, string>()
{
{ 1, "foo" },
{ 2, "bar" }
};
var result = myDict.GetValue(5, "baz");
However, for some unknown reason, Visual Studio refuses to compile my code with the following compile-time error: "The type 'System.Web.HttpContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Web'" . This error tells me that the compiler selected the GetValue extension method in the WebExtensions class instead of the one in the DictionaryExtension class.
I was able to get around the problem with the following:
var result = DictionaryExtensions.GetValue(myDict, 5, "baz");
but I'm trying to understand why the compiler was confused in the first place. Does anybody know why?
Another option is to break your 2 Extension classes out into separate namespaces and do not add a using statement where the WebExtensions class resides in your consuming code. That way the compiler won't try and resolve GetValue to WebExtensions.
Just do what the compiler says and add a reference to System.Web.dll. Then it should compile.
Your external assembly where these extension method classes exist take a dependency on System.Web.dll. The compiler should be able to figure out the overload, but in order to do so, it needs to reference the assembly where HttpContext exists, which is in System.Web.dll.
On the other hand if you don't want your project that consumes the extension method assembly to take a dependency on System.Web.dll, then you need to define those 2 extension method classes in separate assemblies.
#Steve Danner has a good solution too: put the two extension method classes into different namespaces in the same assembly, and omit the using statement for the namespace that contains the WebExtensions class.
I run into this occasionally with things like System.Runtime.Serialization, System.ServiceModel.Activation, etc. It can happen when you have a dependency that is twice-removed. In other words your root project depends on an assembly which depends on a type another third assembly.

Why can't a static and non-static method share the same signature?

C# provides following signature characteristics to be used while function overloading.
We know that for overloading takes into consideration only arguments; their number and types, but the objective of polymorphism is to provide same name but different usage depending upon calling strategy.
If I have a class containing two methods with the same name and signature, while one is static and another is not, C# compiler throws an error; "Class already defines a member called 'foo' with the same parameter types".​The call to both the methods are going to be different; one with the object name and the static one with a class name. Hence there is no ambiguity with calling strategy. Then why does it throw an error?
class Example {
public void foo() { }
public static void foo() { }
}
class Program
{
static void Main(string[] args)
{
Example e = new Example();
e.foo();
}
}
Reason why it is throwing an error is that static methods can be called from non-static methods without specifying type name. In this case, compiler won't be able to determine, which method is being called.
public class Foo()
{
public static void MyMethod() {};
public void MyMethod() {}
public void SomeOtherMethod()
{
MyMethod(); // which method we're calling static or non-static ?
}
}
EDIT
Just found this SO post regarding your case. You might want to check it also.
This error occurs because this is how the behavior is defined in the C# Language Specification. Any "ambiguous" usage (or ways to disambiguate such) is irrelevant, although such reasoning and edge-cases may have led the designers to not explicitly allow such a differentiation .. or it might simply be a C# codification of an underlying .NET CLI/CLR restriction1.
From "3.6 Signatures and overloading" in the C# specification (and in agreement with the linked documentation), formatted as bullets:
The signature of a method consists of
the name of the method,
the number of type parameters, and
the type and kind (value, reference, or output) of each of its formal parameters ..
Method modifiers, including static, are not considered as part of the method signature here.
And, from "1.6.6 Methods" we have the restriction and an agreeing summary:
The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and {the number, modifiers, and types of} its parameters..
This restriction applies before (and independently of) the method being considered for polymorphism.
Also, as a closing note: instance methods must be virtual or accessed through an interface to be run-time polymorphic in C#. (Both method hiding and method overloading are arguably a form of compile-time polymorphism, but that's another topic..)
1There is support for this simply being the result of a restriction of the .NET CLI/CLR itself that is not worth bypassing (ie. for interoperability reasons). From "I.8.6.1.5 Method signatures" in ECMA-335:
A method signature is composed of
a calling convention [CLS Rule 15: "the only calling convention
supported by the CLS is the standard managed calling convention"],
the number of generic parameters, if the method is generic,
[omitted rule]
a list of zero or more parameter signatures—one for each parameter of the method—
and,
a type signature for the result value, if one is produced.
Method signatures are declared by method definitions. Only one constraint can be added to a
method signature in addition to those of parameter signatures [CLS Rule 15: "The vararg constraint is not part of the CLS"]:
The vararg constraint can be included to indicate that all arguments past this point are
optional. When it appears, the calling convention shall be one that supports variable
argument lists.
The intersection between the C#/CLS and ECMA signature components is thus the method name, "the number of generic parameters", and "a list of zero or more parameter signatures".
I feel your question is "why did the standard choose to forbid declaring two methods that differ only by the static keyword?", and therefore the answer "because the standard says so" does not look appropriate to me.
Now, the problem is, there could be any reason. The standard is the Law, and it can be arbitrary. Without the help of somebody who participated to the language's design, all we can do is speculate about the reasons, trying to uncover the spirit of the Laws.
Here is my guess. I see three main reasons for this choice:
Because other languages say so.
C++ and Java are inspirational languages for C#, and it makes sense to observe the same overloading rules as those languages. As to why it is this way in these languages, I don't know. I found a similar question on SO about C++, although no answer is given as to why it is this way (outside of "the standard says so").
Because it creates ambiguity that need to be resolved.
As others and OP noted, allowing the same signatures excepted for the static keyword forces the user to call the methods in an unambiguous way (by prefixing the class name or the instance name). This adds a level of complexity to the code. Of course this can already be done with fields and parameters. However some don't agree with this usage and prefer to choose different names (prefixing the fields with _ or m_) for the fields.
Because it does not make a lot of sense in OOP.
This is really my understanding here, so I could be completely wrong (at least #user2864740 thinks that the argument is dubious -- see comments), but I feel like static members are a way to introduce "functional programming" in OOP. They are not bound to a specific instance, so they don't modify the internal state of an object (if they modify the state of another object, then they should be a non-static method of this other object), in a way they are "pure".
Therefore I don't understand how a "pure function" could be semantically close enough of a regular object method so that they would share the same name.
The same question was asked to Eric Gunnerson, who worked on the C# language design team, and his answer was:
It is true that there would be no ambiguity between the two functions as far as a compiler is concerned. There would, however, be a considerable potential for confusion on the part of the user. It would be tough to find the right method in documentation, and once you did, hard to be sure that you are calling the right version (ie you could accidentally call the static version when you wanted the instance version).
Therefore, the reason it is not allowed is by design.
i) Problem hypothesis - obtain the following behavior :
Be able to call a static method off of a class: e.g. MyClass.MySpecialMethod()
Also be able to call a non-static method with the same return type, name and arguments off of an instance of the same class: e.g. instanceOfMyClass.MySpecialMethod()
ii) Context :
Reproduce the behavior inside an application that uses Dependency Injection.
Most of today's programming uses DI - it is almost an anti-pattern to call a non-static method off of a direct instance of a dependency (without that dependency having been previously injected with DI).
iii) Solution :
class Program
{
static void Main(string[] args)
{
// instead of class initialization we would have these registrations, e.g.:
// diContainer.Resolve<IMyApplication>().With<MyDIApplication>();
// diContainer.Resolve<ITerminator>().With<Terminator>();
IMyApplication app = new MyDIApplication(new Terminator());
app.Run();
}
public interface IMyApplication { void Run(); }
public class MyDIApplication : IMyApplication
{
private readonly ITerminator terminator;
public MyDIApplication(ITerminator terminatorDependency)
{
this.terminator = terminatorDependency;
}
public void Run()
{
terminator.Terminate(); // instance method call
Terminator.Terminate(); // static method call
}
}
public interface ITerminator { void Terminate(); }
public class Terminator : ITerminator
{
public static void Terminate() => Console.WriteLine("Static method call.");
void ITerminator.Terminate() => Console.WriteLine("Non-static method call.");
}
}
Conclusion:
Yes, the signatures of the two Terminate methods are not identical, because the non-static method is an explicit implementation of the interface which does not conflict with the static method,
But in truth, when using this solution in the context of dependency injection, what we really care about is the outcome, not the plumbing - which is that we managed to call a static method off a class, with practically the same return, name and args as a non-static method off an instance of that class injected with DI.
Check out this simple pseudo-code:
class A
{
public void B(){...}
public static void B(){...}
}
...
A A = new A();
A.B(); // <== which one is going to be called?

Why am I getting this definition reference error?

I am using TaskBar methods defined within the namespace Microsoft.WindowsAPICodePack.Taskbar. Specifically, I'll focus on SetProgressState for this question.
Here is the meta-definition I get when I ask for the definition of SetProgressState:
namespace Microsoft.WindowsAPICodePack.Taskbar
{
public class TaskbarManager
{
public void SetProgressState(TaskbarProgressBarState state);
public void SetProgressState(TaskbarProgressBarState state, IntPtr windowHandle);
public void SetProgressState(TaskbarProgressBarState state, System.Windows.Window window);
}
}
Obviously, I have omitted most of that class's definition just to highlight the one method's overloads.
To this point, I have been using the single-parameter overload and have had no issues. However, today I attempted to use the two-parameter overload that accepts an IntPtr as its second parameter.
When I did that, I started getting this error during build:
The type 'System.Windows.Window' is defined in an assembly that is not
referenced. You must add a reference to assembly
'PresentationFramework, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'
So my question is why I did not get an error for using the single-parameter overload, but I do get an error for referencing one of the others (and for the wrong one)?
Edit (for addition sub-question):
I also tried the following, which made no difference:
SetProgressState(myState, (IntPtr) myWindowHandle);
I thought that by casting explicitly, I would avoid the compiler confusion in realizing the appropriate overload, but that was not the case.
According to the MSDN page on Overload Resolution, the compiler will start by selecting the potential candidates
Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way
then, the best target is selected:
If the set contains only one function member, then that function member is the best function member.
My understanding here is that the compiler doesn't even consider the 2 arguments methods when you call it with 1 argument. However, when you use the 2 arguments version, it needs information about the argument types. In this case, it needs to know what System.Windows.Window is to be able to determine which overload you want to call.
Example
Imagine you have 2 classes in separate Class Libraries
class Foo
{
}
class Bar : Foo
{
}
and 4 methods in an other library
static void Do()
{
}
static void Do(Foo foo)
{
}
static void Do(Bar bar)
{
}
static Foo Get()
{
return new Bar();
}
You reference the Methods Library and the Library Containing Foo, but not the library containing Bar.
Then, in your application, you obtain an object of type Foo from the Methods Library (it could be a Bar too, but you don't know). How is the compiler supposed to resolve an eventual call to Do() with arguments?
It can't unless it has the type information for Bar as well.
As for your subquestion, it's a result of the above plus the fact that a cast doesn't necessarily force an overload to be chosen. Let's imagine that System.Windows.Window derives from IntPtr for a moment. Casting the argument to IntPtr doesn't help the compiler resolve the overload at all (see above example).
Since the type information is not present, the compiler emits an error because it can't know for sure. Honestly, for compilers, that's a feature.
I'll expand my comments here for clarity. Your project isn't able to find System.Windows.Window. I mispoke in my comment when I said you need to put in:
using System.Windows;
To the file.
Instead, the project needs to have a reference to System.Windows. The reference you want is given to you in the error message: PresentationFramework. You will also need to include PresentationCore(a similar error will pop up telling you to add a reference to PresentationCore).
The type 'System.Windows.Window' is defined in an assembly that is not referenced. You must add a reference to assembly 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

Mixing generic methods and extension methods

I created the Class1.GetChild<T>() where T : DependencyObject extension method in lib1.dll assembly. After that, all assemblies that depends on lib1.dll failed to compile with error:
The type 'System.Windows.DependencyObject' is defined in an assemebly
that is not referenced. You must add a reference to assembly
'WindowsBase' etc...
Why dependent assemblies requires WindowsBase even if they don't use GetChild?
.
To reproduce (vs2010 .net4):
lib1.dll (references WindowsBase)
namespace lib1
{
public static class Class1
{
public static T GetChild<T>(this DependencyObject src) where T : DependencyObject
{
return default(T);
}
}
public static class Class2
{
public static int SomeExtMethod(this string src)
{
return 0;
}
}
}
lib2.dll (references lib1 but not WindowsBase)
using lib1;
class someClass
{
void someFct()
{
"foo".SomeExtMethod(); // error: The type 'System.Windows.DependencyObject'
// is defined in an assemebly that is not referenced.
// You must add a reference to assembly 'WindowsBase' etc..
}
}
.
Update:
I think there's definitly something when mixing generic methods and extension methods. I tried to demonstrate the issue in the following sample:
// lib0.dll
namespace lib0
{
public class Class0 { }
}
// lib1.dll
using lib0;
namespace lib1
{
public static class Class1
{
public static void methodA<T>() where T : Class0 { } // A
public static void methodB(Class0 e) { } // B
public static void methodC(this int src) { } // C
}
public static class Class2
{
public static void methodD(this String s) { }
}
}
// lib2.dll
using lib1;
class someClass
{
void someFct()
{
Class2.methodD(""); // always compile successfully
"".methodD(); // raise the 'must add reference to lib0' error depending on config. see details below.
}
}
A, //B, //C -> compile ok
A, B, //C -> compile ok
//A, B, C -> compile ok
A, //B, C -> raise error
A, B, C -> raise error
//A means methodA is commented. As Damien pointed out, type inference might play some role. Still curious to know the ins and outs.
Your situation has been answered by Microsoft here:
https://connect.microsoft.com/VisualStudio/feedback/details/668498/problem-with-extension-method-in-c-compiler
There are other use-cases as well independent of extension methods which produce this error wrongly.
Consider this:
Define a generic method in a type, say TP1, defined in library say LB1.
Type constrain the generic method on some type defined in some other library LB2.
Define another method in TP1.
Now in your library reference only LB1 and try to call the second method of type TP1
If you don't use TP1 but some other type defined in LB1, you do not get the error.
Also, even if one of the method of type TP1 expects a parameter of the type defined in LB2 (and you do not call this method) it does not produce this error
When one assembly depends on another assembly, the first assembly also depends on all the dependencies of the other--regardless of what is used. Assembly dependencies are effectively decoupled, another version of either assembly can be deployed after compilation, the compiler can't know that under circumstances like this one or more of the dependencies in the second assembly won't be used by the first assembly.
To solve the issue you can simply add a reference to WindowsBase.
Or, as prashanth points out, put the SomeExtMethod into a different assembly so code that uses that doesn't need to take a dependency on WindowsBase.
Update:
If you don't use anything from an assembly, you don't need any of its dependencies. But, as soon as you use one assembly, you need all the dependencies of that assembly as well. This is apparent in the way Visual Studio add references. If you add a reference to an assembly, it will copy all the dependent assemblies (not registered in the GAC) into your debug/release directories along with the assembly you added.
Update:
As to the compile error: that's the way it was written--there may be no other reason. Is it a good idea to get a compile error if you don't reference dependent assemblies? Maybe, you're likely to use something from a reference and that might use something directly from the references references--better a compile error than a deployment error.
Why not a compile error on every non-referenced secondary dependency? Again, it was written that way. Maybe an error here too would be good; but that would be a breaking change and would require really persuasive reasons.
I'm not sure this can be answered by anyone other than someone on the compiler team. I'm now thinking that it's to do with type inference - but whereas §7.6.5.1 Method Invocations talks about inference, §7.6.5.2 Extension method invocations is silent on the matter - despite the fact that inference obviously does take place when searching for applicable extension methods.
I think it's attempting some form of inference before it's performing the comparison on identifiers (which would immediately rule out the extension method since it's got the wrong name). Obviously, it can't perform any form of inference for this type if it's unable to understand the type constraints.
Hence, when you change your type constraint to just class, it now successfully passes over this method - it can infer a type parameter, but it now eliminates this extension method successfully.
When you reference another assembly, I assume the compiler needs to be able to parse any method signatures defined in that assembly, so it knows where to go to find that function if it sees a call to it.
If you replace your GetChild() function with
public static T GetChild<T>(this T src)
{
if (typeof(T) == typeof(DependencyObject)) return default(T);
else return default(T);
}
or something similar to that, it does not require you to include the reference to WindowsBase that you're running into. But if you add where T : DependencyObject to the signature, it does require it.
Effectively, you can use whatever assembly references you want in a project, so long as you don't expose them in any way. Once you expose them, then every other project which uses your library needs to be able to handle them, and thus requires those references themselves.
Maybe ILMerge would solve this problem. The idea is you create 2 dlls and merge them into one. That way you can have a single dll but reference it twice. Then way you can separate the GUI code from other code and only add the reference that you need to the particular project.
The answer is simple. It is because the method is decalre as public. This mean that it is visible to lib2.dll (in your case.) In other word you can call this method.
It also has a constrain that only classes inherited from DependencyObject can call this method. So that is the reason why you need to reference 'WindowsBase'.

object - How top most base class got Method. [Extension Method]

Yesterday i gone through some article about EventAggregator, there some shot of code written like this,
(Message.Text as object).PublishEvent(PublishEventNames.MessageTextChanged);
public static class ExtensionServices
{
//Supplying event broking mechanizm to each object in the application.
public static void PublishEvent<TEventsubject>(this TEventsubject eventArgs, string eventTopic)
{
ServicesFactory.EventService.GetEvent<GenericEvent<TEventsubject>>()
.Publish(new EventParameters<TEventsubject> { Topic = eventTopic, Value = eventArgs });
}
}
My question is, how the object got the method "PublishEvent". Is my OOP understanding is wrong?
It was implemented as an Extension Method on the object class.
For example, this extension method (from the linked article):
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
Is defined on the String class (by using the this String syntax and a static method on a static class) .
In the project that this is defined in String now has a WordCount method (so long as it is also in the correct namespace).
Extension methods are not actually part of the object that you appear to call the method on. Extension methods are in an additional lookup scope that the compiler looks in after looking for the method in the scope of the object itself.
So, for a method call like obj.MyExtension(), the compiler will look for "MyExtension" in the members of the type of the obj variable. It won't find any matches, because "MyExtension" isn't defined in the object's type. The compiler then looks for extension methods named "MyExtension" that are available in the current scope (because of using clauses) that have a this parameter whose type matches the type of the obj instance variable. If a match is found, then the compiler generates code to make a static method call that other method, passing obj in the this parameter.
I believe the extension methods scope is a "last chance" lookup - if the compiler can't find "MyExtension" in the available extensions, the next step is to fail with a compile error.
The tricky thing with extension methods is they're only accessible when you have added the appropriate using clause to the current source file and added a reference to the appropriate assembly that implements the extensions to bring them into scope.
Intellisense doesn't help you resolve these names by adding the appropriate using clause for you. As a user, you get used to calling a particular method on a particular type of object, and you mentally associate that method as being part of that type. When you're fleshing out a new source file it's very common to write calls to that method as you normally would and get "not found" compiler errors because you forgot to reference the namespace / assembly containing the extension method definition(s) to your source file.
The this part of this TEventsubject eventArgs determines that this is an Extension method.
It is only syntactic sugar to be able to write
TEventsubject eventArgs;
eventArgs.PublishEvent("topic");
Instead of
TEventsubject eventArgs;
ExtensionServices.PublishEvent(eventArgs, "topic");
PublishEvent is an extension method.
You can tell by the definition of the method, which includes the this keyword in the arguments list.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Extension methods are very useful syntactically; but they should be used judiciously:
1) They can clutter Intellisense if too many extensions are added for non-specific types (such as an object).
2) They should be used to augment class/interface inheritance, not replace it. IMO, If a method is shared across completely unrelated types, then it is a good candidate for an extension method. But if it is shared across related types, then it is a better candidate for a method in a base class.

Categories

Resources