I have referenced a dll in a asp.net 2.0 web site developed in Visual Studio. The person who supplied the dll said to reference it and instantiate a class called Subjects.
I have referenced it and if I type:
Subjects mySubjects = new Subjects();
it appears to be 'found' as 'Subjects' appears in light blue text.
If I then try to access a method by writing this:
string ProjectSubject = mySubjects.GetSubject(ProjectID);
again, it seems to be 'found' in that intellisense, as soon as you type the full stop after mySubjects shows the methods available to be called.
So far, so good. But, when I try to run the page, I get a compile error which is:
No overload for method 'Subjects' takes 0 arguments.
I don't understand. I thought you always had to reference a class with
someClass myClass = new someClass();
No overload for method 'Subjects' takes 0 arguments.
This means that there is no parameterless constructor defined for Subjects. Intellisense should show you the possible options when you type the initial opening parenthesis, otherwise look up the class in object browser to see the possible constructors (there could be more than 1).
It is also possible that there is no public constructor defined on that class, however this is unlikely as the author has told you to "instantiate an instance of Subjects". Again, object browser should tell you what's available.
Apparently the constructor for Subjects takes a parameter.
I obviously don't know if you have any sort of documentation for your assembly or not.
But you should be able to Visual Studio's 'Object Browser' feature to inspect the type, and from there perhaps figure out what type of parameter it takes.
Related
I have a huge code base and I recently made a change where I changed the type of a parameter from String to a custom class. On the next compile I got all the areas where the impact was, but areas where the input type was of type Object failed. for e.g.
String str = "32"
int i = Convert.ToInt32(str)
Now I have changed String to a new custom type lets say MyCustomClass I would now want following code to fail on next compile
MyCustomClass str = new MyCustomClass("32")
int i = Convert.ToInt32(str)
but it won't as Convert.ToInt32 also accepts type Object. Is there some way I can make a change in MyCustomClass that it's not considered Object anymore.
Please note: Convert.ToInt32 is only used for sample I have many more such functions, so please focus your suggestion/answer to question asked.
Override ToString() and IConvertible
You said in the comments that your intentions are to find places where your object, which had previously been treated as a string, and are now being treated as an object.
In these situations typically, the third-party code would call .ToString() on your object to get something which it can use.
So, Convert.ToInt32(str) is equivalent to Convert.ToInt32(str.ToString()).
If you implement ToString() and IConvertible to return whatever your old version of str looked like then it should continue to work in the same way as the old version.
Probably.
Sorry I know that is not the 100% perfect compile time answer you were looking for, but I think you also know very well that your MyCustomClass will always be considered object.
Possible compile time answer:
Write a tool which uses reflection to iterate over every class/struct/interface in every system/third-party DLL.
Output a load of CS files which contain all these same classes, but just throw NotImplementedException.
(T4 could help you do this)
Compile these classes into dummy.dll
Your .csproj now references only this one dummy.dll, instead of the real dlls.
Your project should compile fine against the dummy dll.
Look at your dummy.cs files and delete any use of object.
Re-compile... and suddenly you get a load of compile time errors showing you anywhere you are using an object.
Impliment an implicit cast from MyCustomClass to String.
public static implicit operator string(MyCustomClass str)
{
return "Legacy respresentation of str";
}
This allows the complier the choice of choosing ToInt32(Object) or ToInt32(String), and I bet it favours the later.
This way all your existing function calls will remain the same so you wont have to be concerned about third party implentation details.
(Sorry, I am not at a computer right now so I can`t test that my assumtion is correct. If you do test this, be sure to consider extension methods, as they can affect the conpilers desision making in unexpected ways)
Have have big problem with Visual Studio 2013 and 2015. In one class, i have defined this two methods:
public List<T> LoadData<T>(string connectionStringName = "", string optWherePart = "", params object[] parameter)
public List<T> LoadData<T>(string optWherePart, params object[] parameter)
I only want to call the second method like this:
....LoadData<Config_Info>("ConfigName LIKE 'Version' AND UserName LIKE '' AND PlugInName Like ?", parameter: ProductName);
If i go to definition in Visual Studio 2013, i come to the second method declaration, but in Visual Studio 2015, i come to the first. Both solutions are
absolutly identically.
Even the compiled result is different, so if i compile the same solution with VS 2015, the program stops working.
This is a very strange behaviour.
Does any one has an idea, what the differences are?
This is based on the C# 5 specification, but since the C# 6 specification doesn't appear to have been published yet that's the best I can do. It's also an attempt to invoke Cunningham's Law.
As a preliminary, in the language of s7.5.3.1 ("Applicable Function Member") of the spec, both function members are applicable (either of them could be called if the other didn't exist) in their expanded form (the params object[] can't be fulfilled by the string ProductName so is converted to an object argument).
Thus we move on to s7.5.3.2 ("Better Function Member") in order to decide which of the two is the better function to call.
Firstly, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list:
{ string "ConfigName [...]", string ProductName }
Next, [p]arameter lists for each of the candidate function members are constructed in the following way:
The expanded form is used if the function member was applicable only in the expanded form.
Optional parameters with no corresponding arguments are removed from the parameter list
The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.
This gives us the following:
{ string connectionStringName, object parameter } (optWherePart removed, params expanded)
{ string optWherePart, object parameter } (params expanded)
We then have a sequence of comparisons to make to decide which of these is the better function member. Calling one Mp and one Mq, these go as follows:
If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
No difference here
Otherwise, if Mp is applicable in its normal form and Mq has a params array and is applicable only in its expanded form, then Mp is better than Mq.
No difference here; both are in their expanded form
Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. This can occur if both methods have params arrays and are applicable only in their expanded forms.
Not 100% on this one. Both our argument lists use 2 of the parameters from the original function definitions. I think this is solely meant to distinguish between one case where both arguments went into the same params array and one where one went into the array and one went into a normal argument.
Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
Aha! Our first argument list is missing optWherePart, which needed a default argument, so the second argument list is better! So VS2015 is wrong!
... but wait. What does this last bullet even mean? Mp and Mq are specifically parameter lists where [o]ptional parameters with no corresponding arguments are removed. There is no way either of them could not have a corresponding argument because if they didn't, they'd have been removed.
In conclusion, I can't tell whether this is a bug in the old compiler, the new compiler... or the C# specification.
I've found a blog post by SLaks that also seems to think the old behaviour was a bug. The blog states that Roslyn had fixed this by making the compiler fail, and that's not what I see any more. Maybe they changed their minds?
Edit: Update! My Roslyn bug report resulted in a change to the compiler to ensure that, in this case, the second overload is picked. This appears to be because of the default arguments need to be substituted wording above. I still think the spec is ambiguous, so I'm disappointed that only a code change was made (and not a spec change, or even a discussion about why the second overload is the better one), but at least the VS2015 runtime beaviour is now the same as it was in VS2013.
I am using Visual Studio 2010 with two projects.
One contains a project referencing Microsoft's Exchange.WebServices dll(ver1.2) for accessing ExchangeServices. I created a class which contains some helper methods and wrappers to carry out various tasks while connected to an Exchange server(through the ExchangeService API). The ExchangeService constructor can accept an enum of ExchangeVersion, to specify the server version info. So I created two constructors within my class.
public class ExchangeConnector(string ver)
{
// Property assignments
}
public class ExchangeConnector(ExchangeVersion ver)
:this(ver.toString()) //Using(or not using) "this", doesn't seem to matter...
{ }
I created the constructor which accepts a string parameter, so that other projects don't necessarily need to add the Exchange.WebServices library.
But then I ran into an un-foreseen issue.
When I create an instance of ExchangeConnector("Exchange2007_SP1") in my second project(that does not contain a reference to the Exchange.WebServices dll), Intellisense doesn't pick the right constructor and doesn't show any pre-compile errors. When I force the build, though, I get the following error:
Error: The type 'Microsoft.Exchange.WebServices.Data.ExchangeVersion' is defined
in an assembly that is not referenced. You must add a reference to assembly
'Microsoft.Exchange.WebServices, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'.
I am not even using the constructor with the ExchangeVersion enum reference, but it requires me to have a reference to it?
If I comment out the constructor with the ExchangeVersion enum, everything compiles, works, no run-time errors.
OR
If I modify the overload constructor so Intellisense can't possibly confuse the two, such as:
public class ExchangeConnector(string url, ExchangeVersion ver)
{
// Property assignments
}
When I call ExchangeConnector("Exchange2007_SP1"), the code compiles and works fine. No runtime errors.
It is almost as though VS can't resolve which constructor to properly use. Now I know I can add the reference to the second project and be done with it, but I am curious as to why VS is doing this. Any ideas?
After inspiration from Scott(the other one) and the link provided by CodeCaster, I think I finally found my answer.
It as part of the C# Language Specification(Visual Studio .Net 2003 Edition).
In Section 10.10 Instance Constructors:
An instance constructor initializer of the form base(argument-listopt) causes an instance constructor from the direct base class to be invoked. That constructor is selected using argument-list and the overload resolution rules of Section 7.4.2. The set of candidate instance constructors consists of all accessible instance constructors contained in the direct base class (including any default constructor, as defined in Section 10.10.4). If this set is empty, or if a single best instance constructor cannot be identified, a compile-time error occurs.
Diving down further to the definition...
In Section 7.4.2 Overload resolution:
Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases:
Given the set of applicable candidate function members, the best function member in that set is located.
If the set contains only one function member, then that function member is the best function member.
Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Section 7.4.2.2.
If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a compile-time error occurs.
And even further...
Section 7.4.2.2 Better function member[3]
[3][http://msdn.microsoft.com/en-us/library/aa691338(v=vs.71).aspx]
Given an argument list A with a set of argument types {A1, A2, ..., AN} and two applicable function members MP and MQ with parameter types {P1, P2, ..., PN} and {Q1, Q2, ..., QN}, MP is defined to be a better function member than MQ if
for each argument, the implicit conversion from AX to PX is not worse than the implicit conversion from AX to QX, and
for at least one argument, the conversion from AX to PX is better than the conversion from AX to QX.
When performing this evaluation, if MP or MQ is applicable in its expanded form, then PX or QX refers to a parameter in the expanded form of the parameter list.
So in summary:
A constructor with the same number of arguments must be evaluated through implicit conversion as to which function member(constructor) would be better.
Hence why I needed to add the reference to the second project so the compiler could determine which constructor was better.
If the constructors don't have the same number of arguments, evaluation doesn't need to occur, and the compiler doesn't need the reference to the second project.
It makes sense to me that if your project is referencing another project with an overloaded constructor where one of those constructors accepts a referenced library, that your calling project would need that reference to compile even though you aren't using that particular constructor. Wouldn't the compiler need that reference to decide which constructor to use? Maybe I'm missing something, but it seems logical to me that it's working correctly.
Please, help me to explain the following behavior:
dynamic d = 1;
ISet<dynamic> s = new HashSet<dynamic>();
s.Contains(d);
The code compiles with no errors/warnings, but at the last line I get the following exception:
Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.Generic.ISet<object>' does not contain a definition for 'Contains'
at CallSite.Target(Closure , CallSite , ISet`1 , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
at FormulaToSimulation.Program.Main(String[] args) in
As far as I can tell, this is related to dynamic overload resolution, but the strange things are
(1) If the type of s is HashSet<dynamic>, no exception occurs.
(2) If I use a non-generic interface with a method accepting a dynamic argument, no exception occurs.
Thus, it looks like this problem is related particularly with generic interfaces, but I could not find out what exactly causes the problem.
Is it a bug in the compiler/typesystem, or legitimate behavior?
The answers you have received so far do not explain the behaviour you are seeing. The DLR should find the method ICollection<object>.Contains(object) and call it with the boxed integer as a parameter, even if the static type of the variable is ISet<dynamic> instead of ICollection<dynamic> (because the former derives from the latter).
Therefore, I believe this is a bug and I have reported it to Microsoft Connect. If it turns out that the behaviour is somehow desirable, they will post a comment to that effect there.
Why it compiles: the entire expression is evaluated as dynamic (hover your mouse over it inside your IDE to confirm), which means that it is a runtime check.
Why it bombs: My (completely wrong, see below) guess is that it is because you cannot implement a dynamic interface in such a manner. For example, the compiler does not allow you to create a class that implements ISet<dynamic>, IEnumerable<dynamic>, IList<dynamic>, etc. You get a compile-time error stating "cannot implement a dynamic interface". See Chris Burrows' blog post on this subject.
http://blogs.msdn.com/b/cburrows/archive/2009/02/04/c-dynamic-part-vii.aspx
However, since it's hitting the DLR anyway, you can make s completely dynamic.
dynamic s = new HashSet<dynamic>;
s.Contains(d);
Compiles and runs.
Edit: the second part of this answer is completely wrong. Well, it is correct in that you can't implement such an interface as ISet<dynamic>, but that's not why this blows up.
See Julian's answer below. You can get the following code to compile and run:
ICollection<dynamic> s = new HashSet<dynamic>();
s.Contains(d);
The Contains method is defined on ICollection<T>, not ISet<T>. The CLR doesn't allow an interface base method to be called from a derived interface. You usually doesn't see this with static resolution because the C# compiler is smart enough to emit a call to ICollection<T>.Contains, not the non-existing ISet<T>.Contains.
Edit: The DLR mimics the CLR behavior, that's why you get the exception. Your dynamic call is done on an ISet<T>, not an HashSet<T> the DLR will mimics the CLR: for an interface, only interfaces methods are searched for, not base interfaces (contrary to classes where this behavior is present).
For an in-depth explanation, see a previous response of mine to a similar question:
Strange behaviour when using dynamic types as method parameters
Note that the type dynamic doesn’t actually exist at run-time. Variables of that type are actually compiled into variables of type object, but the compiler turns all the method calls (and properties and everything) that involve such an object (either as the this object or as a parameter) into a call that is resolved dynamically at runtime (using System.Runtime.CompilerServices.CallSiteBinder and related magic).
So what happens in your case is that the compiler:
turns ISet<dynamic> into ISet<object>;
turns HashSet<dynamic> into HashSet<object>, which becomes the actual run-time type of the instance you’re storing in s.
Now if you try to invoke, say,
s.Contains(1);
this actually succeeds without a dynamic invocation: it really just calls ISet<object>.Contains(object) on the boxed integer 1.
But if you try to invoke
s.Contains(d);
where d is dynamic, then the compiler turns the statement into one that determines, at runtime, the correct overload of Contains to call based on the runtime type of d. Perhaps now you can see the problem:
The compiler emits code that definitely searches the type ISet<object>.
That code determines that the dynamic variable has type int at runtime and tries to find a method Contains(int).
ISet<object> does not contain a method Contains(int), hence the exception.
ISet interface does not have a method 'Contains', HashSet does however?
EDIT
What i meant to say was the binder resolves 'Contains' when given the HashSet concreate type, but doesnt find the inherited 'Contains' method in the interface...
This question already has answers here:
Creating instance of type without default constructor in C# using reflection
(4 answers)
Closed 9 years ago.
Reading existing code at work, I wondered how come this could work. I have a class defined in an assembly :
[Serializable]
public class A
{
private readonly string _name;
private A(string name)
{
_name = name;
}
}
And in another assembly :
public void f(Type t) {
object o = Activator.CreateInstance(t);
}
and that simple call f(typeof(A))
I expected an exception about the lack of a parameterless constructor because AFAIK, if a ctor is declared, the compiler isn't supposed to generate the default public parameterless constructor.
This code runs under .NET 2.0.
[EDIT] I'm sorry but I misread the actual code... The sample I provided doesn't illustrate it. I accepted JonH answer because it provided a good piece of information.
An alternative is:
object obj = System.Runtime.Serialization.FormatterServices
.GetUninitializedObject(t);
which creates the object in memory but doesn't run any constructor. Scary.
See this: Creating instance of type without default constructor in C# using reflection
Here's to the future also, this is in regards to C# 4.0:
Posted by Microsoft on 1/4/2010 at
2:08 PM
We have reviewed your bug and
have determined that the behavior that
you described is by design. We are now
archiving this issue. Thanks for using
Visual Studio and the .Net Framework!
There are many overloads of Activator.CreateInstance, the one that
takes a single type parameter only
invokes the default parameterless
constructor. Constructors that take an
optional parameter like the one in
your example are not default
constructors. To invoke them you need
to:
use an overload that takes an argument array
Pass in Type.Missing as the argument
Specify OptionalParamBinding in the BindingFlags
Here is an example:
Activator.CreateInstance(typeof(MyClassName),
BindingFlags.CreateInstance |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.OptionalParamBinding,
null, new Object[] {Type.Missing}, null);
Thanks,
Weitao Su
Microsoft Corp.
This may not be feasible for you to do, but the simplest thing is to pass the argument list after the type like so:
Activator.CreateInstance(t, "name");
You'll want to think about what f() is really trying to do. Should it be instantiating an object of type A at all? What other classes will it instantiate?
One possibility is to have a switch statement within f() which passes the correct parameters to CreateInstance() for class A. This won't scale, but that may not be an issue for you.
There are two confusing flavors of CreateInstance: one that takes an object of type System.Type as a parameter, another that takes a type parameter T.
First one:
object Activator.CreateInstance(type As Type) { }
Second one:
T Activator.CreateInstance<T>() { }
The second one is the one that doesn't work for a class without a public parameterless constructor.
Note that it almost never makes sense to even use the second one; in any case where it would be used, it would be better to have a where T : new() constraint on your class and simply use T's constructor.
The MSDN documentation agrees:
In general, there is no use for the
CreateInstance in application code,
because the type must be known at
compile time. If the type is known at
compile time, normal instantiation
syntax can be used (new operator in
C#, New in Visual Basic, gcnew in
C++).
EDIT: I may have spoken too soon; it appears the first version isn't supposed to work either.