how can i transform a method (that performs a+b and returns the result) from add(a,b) to a.add(b)?
i read this somewhere and i can't remember what is the technique called...
does it depends on the language?
is this possible in javascript?
In .NET it is called extension methods.
public static NumberExtensions
{
public static int Add(this int a, int b)
{
return a + b;
}
}
UPDATE:
In javascript you could do this:
Number.prototype.add = function(b) {
return this + b;
};
var a = 1;
var b = 2;
var c = a.add(b);
On c# it is named extensions methods:
public static class IntExt
{
public static int Add(this int a, int b)
{
return a + b;
}
}
...
int c = a.Add(b);
say for example you want to do this on integers in C#. You need to define extension methods like this:
public static class IntExtMethods
{
public static int add(this int a, int b)
{
return a+b;
}
}
In C# you can use an Extension Method. In C++, you need to create a member which belongs to the A class which performs the add for you. C does not have objects, so what you're looking for is not possible in C.
If you want to create your own JavaScript class:
function Num(v) {
this.val = v;
}
Num.prototype = {
add: function (n) {
return new Num(this.val + n.val);
}
};
var a = new Num(1);
var b = new Num(2);
var c = a.add(b); // returns new Num(3);
Taking your question literally, I assume you mean transforming this
var add = function(a, b) {
return a + b;
}
to this:
a.add = function(b) {
return this + b;
}
This however only adds that method to a, not to any other object with the same constructor. See Darin Dimitrov's answer for an example of that. Extending the native Number constructor's prototype is not something many would recommend though...
Related
I am writing a class that should ideally have multiple methods of the same signature. Is there a way to force the class to check its methods if all of them follow the same signature?
It would be ideal if the check could be done at compile-time/during build
If you assume the signature to be int <methodName>(string, int, char)
public class Conditions {
// no error
int MethodA(string a, int b, char c)
{
return 0;
}
// no error
int MethodB(string a, int b, char c)
{
return 1;
}
// should throw error because return type does not match signature
string MethodC(string a, int b, char c)
{
return "Should throw an error for this function";
}
}
}
It's sort of cheating, but if you require the developer to register their methods, you can force a compile time error by requiring the method to match a delegate.
This is essentially how event handlers and callbacks work.
namespace Framework
{
public delegate int MyApiSignature(int a, string b, char c);
public class Core
{
static public void RegisterMethod(MyApiSignature method)
{
//Doesn't even have to actually do anything
}
}
}
namespace Custom
{
using Framework;
class Foo
{
public Foo()
{
Core.RegisterMethod(MethodA); //Works
Core.RegisterMethod(MethodB); //Compile-time error
}
public int MethodA(int a, string b, char c)
{
return 0;
}
public int MethodB(int a, string b, byte c)
{
return 0;
}
}
}
You could make a unit test:
[TestMethod]
public void Conditions_MethodsHaveCorrectSignature()
{
var whitelist = new List<string> { "Finalize", "MemberwiseClone" };
var t = typeof(Conditions);
var m = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var item in m.Where(x => !whitelist.Contains(x.Name)))
{
Assert.AreEqual(typeof(int), item.ReturnType);
CollectionAssert.AreEquivalent(new List<Type> { typeof(string), typeof(int), typeof(char) },
item.GetParameters().Select(x => x.ParameterType).ToList());
}
}
Not directly. You could write an analyzer for it using Roslyn, or you could write a unit test that checks the signatures via reflection.
I have a client application that uses classes (and enums) from an external dll which is loaded at runtime and reflected. I know what methods I am expecting to find in the dll and what I am expecting its enums to be called.
I would like to create a delegate that I can use in the client application and which is created from the reflected method at runtime. This approach works when the delegate just has "standard" types, but how can I get this to work if the dll method takes an enum? I can't declare the enum in the delegate as an object since it's a value type, trying the Enum or int does not seem to work either. Is there a way around this? Any help gratefully received!
// e.g. external code
namespace test2
{
public static class test2
{
public static int calc(int a, int b, testEnum c)
{
if (c == testEnum.add) return a + b;
else return a - b;
}
public static int add(int a, int b)
{
return a + b;
}
}
public enum testEnum
{
add, subtract
}
}
// my client code
namespace test1
{
public class TestClient
{
private static Assembly _assembly;
public static void SetUp()
{
const string externalDll = ".../test2.dll";
Assembly assembly = Assembly.LoadFrom(externalDll);
AppDomain.CurrentDomain.Load(assembly.GetName());
_assembly = assembly;
}
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, ??? c); // nothing works here
private _calc calc;
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // not OK
// intended usage
var reflectedEnum = ReflectMe("testEnum", "add");
int threeAgain = calc(1, 2, reflectedEnum);
}
public static T GetExpectedFunction<T>(string functionName) where T : class
{
try
{
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = _assembly.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
catch (Exception e)
{
// "Error binding to target method!"
}
}
}
}
You can bind a delegate with object type to a method taking an enum by creating, at runtime, a dynamic method call with LINQ Expression, and adding data conversions for parameters whose types don't match:
public static T GetExpectedFunction<T>(string functionName) where T : class {
try {
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = Type.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
var inv = typeof(T).GetMethod("Invoke");
var parameters = inv.GetParameters().Zip(foundMethod.GetParameters(), (a, b) => new {
PassedIn = a.ParameterType
, Reflected = b.ParameterType
, Parameter = Expression.Parameter(a.ParameterType)
}).ToList();
if (parameters.All(p => p.PassedIn == p.Reflected)) {
// Bind directly
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
var call = Expression.Call(foundMethod, parameters.Select(
p => p.PassedIn==p.Reflected
? (Expression)p.Parameter
: Expression.Convert(p.Parameter, p.Reflected)
));
return (T) (object) Expression.Lambda(typeof(T), call, parameters.Select(p => p.Parameter)).Compile();
} catch (Exception e) {
// "Error binding to target method!"
return null;
}
}
This implementation pairs up types from the reflected and the delegate methods (see parameters variable), and creates ParameterExpression objects for types that come from the delegate. Then it checks if all parameter types match up (the parameters.All(...) part). This is an optimization for situations when conversions are unnecessary.
If at least one conversion is necessary, the code creates a method call that substitutes the original parameter expressions with conversion expressions where types do not match up, creates a lambda of the requested delegate type, compiles it, and returns it to the caller.
For your code this dynamic method would look like this:
int dynamic_method(int a, int b, object c) {
return test2.test2(a, b, (testEnum)c);
}
There is one solution, you have to create faked Enum (it will be better if you create the exact enum), then you will pass as integer like this:
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, FakedEnum c); // faked enum here
private _calc calc;
public enum FakedEnum
{
}
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // it will be ok
var result= calc(4, 6, (FakedEnum)0);
// intended usage
// var reflectedEnum = ReflectMe("testEnum", "add");
//int threeAgain = calc(1, 2, reflectedEnum);
}
Use dynamic keyword to declare your delegate parameter:
private delegate int _calc(int a, int b, dynamic c);
How to check for integer in one line?
sample.AddRange(Statistics.Select(player => new Stats
{
SeasonFromYear = Convert.ToInt32(seasonFromYear)
}
This one is working for me.
int a;
SeasonFromYear = int.TryParse(seasonFromYear, out a) ? a : default(int);
But for every property i need to declare one variable like a. Without that is it possible to check in one line?
Something like this
sample.AddRange(Statistics.Select(player => new Stats
{
SeasonFromYear = is integer ? then value : else default value
}
You can create extension method:
public static int ToInt(this string v)
{
int a = 0;
int.TryParse(v, out a);
return a;
}
And then:
int number = "123".ToInt();
Edit
Or you can pass integer as out parameter:
public static bool ToInt(this string v, out int a)
{
return int.TryParse(v, out a);
}
usage:
int number = 0;
"123".ToInt(out number);
That's not necessary. If int.TryParse fails, a will be set to default(int). Just use:
int a;
int.TryParse(sessionFromYear, out a);
SeasonFromYear = a;
Or if you really want to do it in one line, you'd have to create you're own wrapper method:
public static int TryParseInline(string in) {
int a;
int.TryParse(sessionFromYear, out a);
return a;
}
...
sample.AddRange(Statistics.Select(player => new Stats
{
SeasonFromYear = Util.TryParseInline(seasonFromYear),
...
})
Have you tried using a safe cast and doing a null-coalescing check in a single line?
SeasonFromYear = seasonFromYear as int ?? default(int);
Try:
int.TryParse(sessionFromYear, out SessionFromYear)
If SessionFromYear can be a property just create a method that will do what you need to do - e.g.:
public int ParseInt(string input)
{
int value;
int.TryParse(input, out value);
return value;
}
and then you can use this method all over the place like this:
SessionFromYear = ParseInt(sessionFromYear);
if you want to make it really fancy you could even create an extension method on the string class and then just do something like sessionFromYear.ToInt()
I know this is old but for one line just declare a in the TryParse:
SeasonFromYear = int.TryParse(seasonFromYear, out int a) ? a : default(int);
Put whatever default value you want where default(int) is.
I have a python script:
def f():
a = None
b = None
return (a, b)
a, b = f()
It's so easy to achieve multiple return values in python.
And now I want to achieve the same result in C#. I tried several ways, like return int[] or KeyValuePair. But both ways looked not elegant. I wonder a exciting solution. thanks a lot.
Use Tuple class.
public Tuple<int,int> f()
{
Tuple<int,int> myTuple = new Tuple<int,int>(5,5);
return myTuple;
}
Unfortunately, C# does not support this. The closest you can get is to use out parameters:
void f(out int a, out int b) {
a = 42;
b = 9;
}
int a, b;
f(out a, out b);
You can obviously do
object F(out object b)
{
b = null;
return null
}
object b;
var a = F(out b)
but better to use Tuple with a functional style,
Tuple<object, object> F()
{
return Tuple.Create<object, object>(null, null);
}
var r = F();
var a = r.Item1;
var b = r.Item2;
but, since in c# you can be explicit, why not define your return type.
struct FResult
{
public object A;
public object B;
}
FResult F()
{
return new FResult();
}
var r = F();
var a = F.A;
var b = F.B;
This seems like a small price to pay for the semantic benefits.
This feature is available in C#7 with .Net 4.7.
private (string a, string b) f()
{
return (a: null, b: null);
// or simply: return (null, null);
}
var (a, b) = f();
Why is it necessary to make a function STATIC while using delegates in C# ?
class Program
{
delegate int Fun (int a, int b);
static void Main(string[] args)
{
Fun F1 = new Fun(Add);
int Res= F1(2,3);
Console.WriteLine(Res);
}
**static public int Add(int a, int b)**
{
int result;
result = a + b;
return result;
}
}
It's not "necessary". But your Main method is static, so it can't call a non-static method. Try something like this (this isn't really a good way to do things—you really should create a new class, but it doesn't change your sample much):
class Program
{
delegate int Fun (int a, int b);
void Execute()
{
Fun F1 = new Fun(Add);
int Res= F1(2,3);
Console.WriteLine(Res);
}
static void Main(string[] args)
{
var program = new Program();
program.Execute();
}
int Add(int a, int b)
{
int result;
result = a + b;
return result;
}
}
Your function needs to be static because you're calling from a static method, Main. You can make the method non-static:
class Program
{
delegate int Fun (int a, int b);
static void Main(string[] args)
{
Program p = new Program(); // create instance of Program
Fun F1 = new Fun(p.Add); // now your non-static method can be referenced
int Res= F1(2,3);
Console.WriteLine(Res);
}
public int Add(int a, int b)
{
int result;
result = a + b;
return result;
}
}
In this case, because you aren't creating an instance of any class, the only alternative is a static function. Were you to instantiate an object of type Program, then you could use an instance method instead.
Delegates basically follow the same rules as methods. In the example provided your delegate must be static because you are calling it from a static method. In the same vein this will not work:
static void Main(string[] args)
{
int Res = Add(3, 4);
Console.WriteLine(Res);
}
public int Add(int a, int b)
{
int result;
result = a + b;
return result;
}
However if you moved things into a non static context like this:
class MyClass
{
public MyClass()
{
Fun F1 = new Fun(Add);
int Res = F1(2, 3);
Console.WriteLine(Res);
}
public int Add(int a, int b)
{
int result;
result = a + b;
return result;
}
}
You can have a delegate with a non-static method.
No need to create a static method to pass in delegate.
But the non static method should be declared in different class and have to be accessed with instance of that class.
DelegateName DN = new DelegateName ( instance of the class . Method Name)