Javascript error calling overloaded methods of a C# class - c#

I'm writing a C# class library, and calling it from some Javascript code (technically Jscript.NET). I recently added some overloaded methods, and Javascript has trouble deciding which one to call, because it doesn't always know the types of its variables. I understand why this is happening in most cases, but I've got one example where I don't understand it.
Here are the overloaded method declarations in the C# class.
public virtual DeviceMessage RequestInUnits(
Command command,
int value,
UnitOfMeasure unit)
public virtual DeviceMessage RequestInUnits(
Command command,
Measurement measurement)
My application has a scripting feature that uses Jscript.NET. Here's some Javascript code that tries to call one of those methods on the C# class.
c.RequestInUnits(Command.MoveAbsolute, 0);
That's not a legal call, because the only method with two parameters expects a Measurement object as the second parameter. However, I would expect a type mismatch error. Instead, here's the compilation error I get.
More than one method or property matches this argument list at line 3 column 1
If I replace the 0 with "", then I get a type mismatch error. Why does Javascript think it can convert a number to an object? Why does it think it can coerce the types to more than one of those methods? Only one method takes two parameters.
This isn't a critical problem, but I don't like it when my library causes confusing error messages in calling code. I'd prefer to avoid that if I can.

Related

I would like to know the difference between function and method in C#

Example code for my question
MessageBox.Show();// is a method and
and private void Example()
{
} //is a function?
is there any real difference or not, please explain
Let's first get the general definition of what function means in a Computer Science sense:
Functions are "self contained" modules of code that accomplish a
specific task. Functions usually "take in" data, process it, and
"return" a result. Once a function is written, it can be used over and
over and over again. Functions can be "called" from the inside of
other functions.
or another definition:
In programming, a named section of a program that performs a specific
task is called a function. In this sense, a function is a type of
procedure or routine. Some programming languages make a distinction
between a function, which returns a value, and a procedure, which
performs some operation but does not return a value.
By these definitions, just about every named code block that can perform a repeatable task when called is a function, though some languages would have that code return a value.
However, in C# according to the ECMA specifications, the word function is very rarely used (comparatively), and can mean something very specifically (depending on the context) or define a large subset of language features.
Notable mentions from the ECMA C# Specifications
Anonymous functions
An anonymous-method-expression or lambda-expression is classified as
an anonymous function
Function members
Function members are members that contain executable statements.
Function members are always members of types and cannot be members of
namespaces. C# defines the following categories of function members:
Methods
Properties
Events
Indexers
User-defined operators
Instance constructors
Static constructors
Finalizers
Async Functions
A method (§15.6) or anonymous function (§12.16) with the async
modifier is called an async function. In general, the term async is
used to describe any kind of function that has the async modifier. It
is a compile-time error for the formal parameter list of an async
function to specify any ref or out parameters.
Local functions
Starting with C# 7.0, C# supports local functions. Local functions are
private methods of a type that are nested in another member. They can
only be called from their containing member.
In short, trying to determine what a function is and isn't in C# is problematic at best (you should worry about other things). Most of the time the terminology of method and function can be used interchangeably, however it also can be used to describe a very specific named language feature (as seen above).
People could argue about the historical definition forever or quote specs to prove the point either way. However, for what you should be concerned with (at this level) is that most things you would think of as methods or functions are actually both (with few exceptions).
A function in C# (or more precise "local function") is a function defined inside another method.
Both examples in the post show "methods" returning a value. There is no naming difference whether method returns a value or void, or whether value returned by a call to the method is used or not.
The other types of syntactic constructs in C# that you can call "function" (in addition to local functions and methods):
constructors
property and event accessors (also you probably should avoid calling them functions, at very least not automatically generated once)
anonymous methods/functions striclty called anonymous function expressions
lambda expressions
finalizers (also you probably should stick with another wrong name than calling it function - "destructor" if you really don't like proper "finalizer").
Your Example() is a method definition, whereas MessageBox.Show() is a method that is being called. MessageBox.Show() also has a definition but it isn't in your code, it is in the .Net code.

Versioning Issues With Optional Arguments

I was reading an article on how optional arguments break when versioning changes.
To paraphrase here.
Let’s look at a quick example of these two concepts at work. Suppose
we have a class with one method having the following signature.
// v1
public static void Redirect(string url, string protocol = "http");
This hypothetical library contains a single method that takes in two
parameters, a required string url and an optional string protocol.
The following shows the six possible ways this method can be called.
HttpHelpers.Redirect("https://haacked.com/");
HttpHelpers.Redirect(url: "https://haacked.com/");
HttpHelpers.Redirect("https://haacked.com/", "https");
HttpHelpers.Redirect("https://haacked.com/", protocol: "https");
HttpHelpers.Redirect(url: "https://haacked.com/", protocol: https");
HttpHelpers.Redirect(protocol: "https", url: https://haacked.com/");
Notice that whether or not a parameter is optional, you can choose to
refer to the parameter by name or not. In the last case, notice that
the parameters are specified out of order. In this case, using named
parameters is required.
The Next Version
One apparent benefit of using optional parameters is that you can
reduce the number of overloads your API has. However, relying on
optional parameters does have its quirks you need to be aware of when
it comes to versioning.
Let’s suppose we’re ready to make version two of our awesome
HttpHelpers library and we add an optional parameter to the existing
method.
// v2
public static void Redirect(string url, string protocol = "http", bool permanent = false);
What happens when we try to execute the client without recompiling the
client application?
We get the following exception message.
Unhandled Exception: System.MissingMethodException: Method not found: 'Void HttpLib.HttpHelpers.Redirect(System.String,
System.String)'....
I'm confused as to why this change will break deployed not recompiled changes.
After changing the method signature which includes an optional parameter it should still work isn't? even if we do not recompile the client application since this is an optional parameter.
Your code needs to be recompiled so that the compiler can generate a call to a new method that takes three arguments. Optional methods are just syntactic sugars, when you don't provide an optional argument the compiler passes the default value for you. But it can't happen if you don't recompile your code and you will attempt to call method with two arguments while three was expected.

Pass a callback function from Visual Basic to C#

I have a .dll written in C# and I use it in Visual Basic for making a Com object. I call C# functions from my Visual Basic code. I'm quite new to this technology and I encountered with such a problem. In C# code I have a method, that receives a callback function as a parameter, gets data from server then calls that callback function. Now I need to to call that function from my Visual Basic code and pass to it a callback.
I think it should look something like this
// C# dll
public bool GetDataFromServer(int someData1, Action<MyCustomType> callback, int someData2)
{
// request to server, get data, create an object of MyCustomType
// call callback and pass MyCustomType object to it as a parameter
}
// Visual Basic part
Public Sub DisplayData(ByRef resp As My_Dll.MyCustomType)
' do something with resp
End Sub
// call Dll method
My_Dll.GetDataFromServer(1, DisplayData, 2) ' I get a compile error
But I can't get it work, it event does not compile. I get a compilation error saying "Argument not optional". I've also tried to pass callback function with AddressOf, but I get an error again saying - "Invalid use of AddressOf operator".
Now my question is - what am I doing wrong? What is the correct way of passing a callback function from Visual Basic to C# and then get it invoked.
Thank you for your time!
Anything containing generics is not visible to COM, so your GetDataFromServer with Action<MyCustomType> is not COM visible. You must define a method on a non-generic class without generic type arguments of itself and without generic parameter or return types.
The usual way of passing a callback in COM is to pass an interface pointer with a method to be called. Avoid the AddressOf approach, however feasible, it's really bad practice once you want the callback to work out-of-process.
A common trick with IDispatch objects is to define a class with a default method with DispId 0 (DISPID_VALUE), which may be invoked by the COM server through IDispatch::Invoke. In some languages, such as JScript, objects may be callable through this technique.
To see how you can do this in VB6/VBA, search for VB_UserMemId. Essentially, you must edit the class file in its raw format (in VBA, you must export it) and add an attribute, such as:
Sub Call()
Attribute Call.VB_UserMemId = 0
End Sub
In VBA, you'd delete the class and import from the edited file. The effect is that the Call method now has DispId 0. You may call it whatever you want, but remember to edit both the Sub name and the Attribute.
In C#, I believe the only ways to achieve such call is with a dynamic variable with:
obj[0]
or through Type.InvokeMember or similar IDispatch::Invoke approaches:
obj.GetType().InvokeMember("", BindingFlags.InvokeMethod, null, obj, null);
The latter is more reliable and you pass the arguments you want, while the former uses a misleading syntax and forces you to pass an argument.
In general, if you control the whole situation and you don't need callable objects, just go for a plain method.
Regarding the AddressOf error, this operator works on module procedures and functions, so the error you see is probably because DisplayOptionQuotes is a method.

Can I pass a method as a parameter?

I am developing several plugin methods that generate a string, and pass it back to my main method. From here, I can then come up with a sequence number. However, I want to avoid integrating the plugin into my main program - basically anything that forces me to change my main program in any way to recognise this plugin is off-limits.
So - in my main program, I generate a string, then match it with other matching strings to figure out the sequence number. The trouble is that I need to know the format of this string so I know where to input this number.
I was thinking about possibly passing in a method that knows the matching functions for this string, but I'm not sure how I can pass a method from one program to another.
I have found this question, but this only appears to be within the same program.
In C#, you can either pass a method as the argument of another method provided that it returns something which the recipient method is expecting. Thus, given this:
public int Foo(){ ... }
public void Bar(int i) { ... }
You can do something like so: ...Bar(this.Foo());
However, I think that what you are after actually are delegates, which are essentially function pointers. This would allow you to call the method to which the delegate points to from some other method.
As a side note, you could consider looking into the Strategy Design Pattern. This pattern allows you to essentially determine which behaviour (logic) to call at run time.
First of all for your case you dont need to pass the method. You can make the method public and access in another program in same namespace like:- ClassObject.Method();... here object should be of class where your method is defined
You can Contain the Return value of function as a parameter while calling if thats what you are trying(like:- testapp(Square(x)) if the type of param is same as of method's Return Type .. In another Case Delegates could be useful.

VB Compiler does not do implicit casts to Object?

I've recently had a strange issue with one of my APIs reported. Essentially for some reason when used with VB code the VB compiler does not do implicit casts to Object when trying to invoke the ToString() method.
The following is a minimal code example firstly in C# and secondly in VB:
Graph g = new Graph();
g.LoadFromEmbeddedResource("VDS.RDF.Configuration.configuration.ttl");
foreach (Triple t in g.Triples)
{
Console.WriteLine(t.Subject.ToString());
}
The above compiles and runs fine while the below does not:
Dim g As Graph = New Graph()
g.LoadFromEmbeddedResource("VDS.RDF.Configuration.configuration.ttl")
For Each t As Triple In g.Triples
Console.WriteLine(t.Subject.ToString())
Next
The second VB example gives the following compiler exception:
Overload resolution failed because no
accessible 'ToString' accepts this
number of arguments.
This appears to be due to the fact that the type of the property t.Subject that I am trying to write to the console has explicitly defined ToString() methods which take parameters. The VB compiler appears to expect one of these to be used and does not seem to implicitly cast to Object and use the standard Object.ToString() method whereas the C# compiler does.
Is there any way around this e.g. a VB compiler option or is it best just to ensure that the type of the property (which is an interface in this example) explicitly defines an unparameterized ToString() method to ensure compatability with VB?
Edit
Here are the additional details requested by Lucian
Graph is an implementation of an interface but that is actually irrelevant since it is the INode interface which is the type that t.Subject returns which is the issue.
INode defines two overloads for ToString() both of which take parameters
Yes it is a compile time error
No I do not use hide-by-name, the API is all written in C# so I couldn't generate that kind of API if I wanted to
Note that I've since added an explicit unparameterized ToString() overload to the interface which has fixed the issue for VB users.
RobV, I'm the VB spec lead, so I should be able to answer your question, but I'll need some clarification please...
What are the overloads defined on "Graph"? It'd help if you could make a self-contained repro. It's hard to explain overloading behavior without knowing the overload candidates :)
You said it failed with a "compiler exception". That doesn't really exist. Do you mean a "compile-time error"? Or a "run-time exception"?
Something to check is whether you're relying on any kind of "hide-by-name" vs "hide-by-sig" behavior. C# compiler only ever emits "hide-by-sig" APIs; VB compiler can emit either depending on whether you use the "Shadows" keyword.
C# overload algorithm is to walk up the inheritance hierarchy level by level until it finds a possible match; VB overload algorithm is to look at all levels of the inheritance hierarchy simultaneously to see which has the best match. This is all a bit theoretical, but with a small self-contained repro of your problem I could explain what it means in practice.
Hans, I don't think your explanation is the right one. Your code gives compile-time error "BC30455: Argument not specified for parameter 'mumble' of ToString". But RobV had experienced "Overload resolution failed because no accessible 'ToString' accepts this number of arguments".
Here's a repro of this behavior. It also shows you the workaround, cast with CObj():
Module Module1
Sub Main()
Dim itf As IFoo = New CFoo()
Console.WriteLine(itf.ToString()) '' Error BC30455
Console.WriteLine(CObj(itf).ToString()) '' Okay
End Sub
End Module
Interface IFoo
Function ToString(ByVal mumble As Integer) As String
End Interface
Class CFoo
Implements IFoo
Function ToString1(ByVal mumble As Integer) As String Implements IFoo.ToString
Return "foo"
End Function
End Class
I think this is annotated in the VB.NET Language Specification, chapter 11.8.1 "Overloaded method resolution":
The justification for this rule is
that if a program is loosely-typed
(that is, most or all variables are
declared as Object), overload
resolution can be difficult because
all conversions from Object are
narrowing. Rather than have the
overload resolution fail in many
situations (requiring strong typing of
the arguments to the method call),
resolution the appropriate overloaded
method to call is deferred until run
time. This allows the loosely-typed
call to succeed without additional
casts.
An unfortunate side-effect of this,
however, is that performing the
late-bound call requires casting the
call target to Object. In the case of
a structure value, this means that the
value must be boxed to a temporary. If
the method eventually called tries to
change a field of the structure, this
change will be lost once the method
returns.
Interfaces are excluded from this
special rule because late binding
always resolves against the members of
the runtime class or structure type,
which may have different names than
the members of the interfaces they
implement.
Not sure. I'd transliterate it as: VB.NET is a loosely typed language where many object references are commonly late bound. This makes method overload resolution perilous.

Categories

Resources