Function having 2 array as input parameter and 2 as output? - c#

Can I create a function C# which has 2 arrays as input parameter and 2 as output?

A method can only have one return value; however, you can use out parameters to return multiple results.
void MyFunction(int[] input1, int[] input2, out int[] output1, out int[] output2)

Use Tuple :
public Tuple<Object[], Object[]> FunctionName(Object[] array1, Object[] array2)
{
//Your code
return new Tuple<Object[],Object[]>({},{});
}

void YourFunc(Int32[] input1, Int32[] input2, out Int32[] output1, out Int32[] output2)
{
output1 = new Int32[] { 1, 2, 3 };
output2 = new Int32[] { 4, 5, 6 };
}
…
YourFunc(i1, i2, out o1, out o2);

You sure can, buddy!
public ArrayGroup MyFunction(myType[] firstArg, myType[] secondArg) {
ArrayGroup result = new ArrayGroup();
/*Do things which fill result.ArrayOne and result.ArrayTwo */
return ArrayGroup;
}
class ArrayGroup {
myType[] ArrayOne { get; set;}
myType[] ArrayTwo { get; set;}
}
Fill in myType with whatever types you want the arrays to be! Like string or int or a complex type!

Sure you can, start with a container for the response:
public class Response
{
public string[] One{get;set;}
public string[] Two{get;set;}
}
And your method might look like
public Response DoSomething(string[] inputOne, string[] inputTwo)
{
// do some thing interesting
return new Respponse
{
One = new string[]{"Hello","World"},
Two = new string[]{"Goodbye","Cruel","World"},
}
}

Option one: Create a type holding the result:
SomeResult MyFunction(T[] arr1, T[] arr2)
{
// ..
return new SomeResult(r1, r2);
}
class SomeResult
{
public SomeResult(T[] a, T[] b) { /* .. */ }
// Rest of implementation...
}
Option two: Return a tuple:
Tuple<T[], T[]> MyFunction(T[] arr1, T[] arr2) { }
Option three: Use out parameters (don't do this):
void MyFunction(T1[] arr1, T[] arr2, out T[] result1, out T[] result2) { }
I prefer option one, and recommend against using out parameters. If the two arguments are of the same type but not interchangeable I'd recommend also creating a type for the argument to make it a single argument function with a single result.

yes you can do this!
You need to pass two output arrays as a reference to the function.
Here is the code example.
Function
private bool ArrayImp(string[] pArray1, string[] pArray2, ref string[] oArray1, ref string oArray2)
{
//Do your work here
//Here oArray1 and oArray2 are passed by reference so you can directly fill them
// and get back as a output.
}
Function Call
string[] iArray1 = null;
string[] iArray2 = null;
string[] oArray1 = null;
string[] oArray2 = null;
ArrayImp(iArray1, iArray2, oArray1, oArray2);
Here you need to pass iArray1 and iArray2 as input array and you will get oArray1 and oArray2 as output.
Cheeerss!! Happy Coding!!

You can pass 2 arrays as parameters to a function, but the function can return a single thing. So you could create an object with the two arrays you need to return, and return that object.

Related

Is it possible to pass List elements as arguments for methods in C#? [duplicate]

Is there any implementation in C# like JavaScript's spread syntax?
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(...arr);
There isn't a spread option. And there are reasons.
Method Parameters aren't an array in C# unless you use the params keyword
Method Parameters that use the param keyword would have to either:
Share the same type
Have a castable shared type such as double for numerics
Be of type object[] (as object is the root type of everything)
However, having said that, you can get similar functionality with various language features.
Answering your example:
C#
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(string.Join(", ", arr));
The link you provide has this example:
Javascript Spread
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
Params
In C#, with same type
public int Sum(params int[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new int[] {1,2,3};
Console.WriteLine(Sum(numbers));
In C#, with different numeric types, using double
public int Sum(params double[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new double[] {1.5, 2.0, 3.0}; // Double usually doesn't have precision issues with small whole numbers
Console.WriteLine(Sum(numbers));
Reflection
In C#, with different numeric types, using object and reflection, this is probably the closest to what you are asking for.
using System;
using System.Reflection;
namespace ReflectionExample
{
class Program
{
static void Main(string[] args)
{
var paramSet = new object[] { 1, 2.0, 3L };
var mi = typeof(Program).GetMethod("Sum", BindingFlags.Public | BindingFlags.Static);
Console.WriteLine(mi.Invoke(null, paramSet));
}
public static int Sum(int x, double y, long z)
{
return x + (int)y + (int)z;
}
}
}
One trick to get a behavior similar to this (without reflection) is to accept params SomeObject[][] and to also define an implicit operator from SomeObject to SomeObject[]. Now you can pass a mixture of arrays of SomeObject and individual SomeObject elements.
public class Item
{
public string Text { get; }
public Item (string text)
{
this.Text = text;
}
public static implicit operator Item[] (Item one) => new[] { one };
}
public class Print
{
// Accept a params of arrays of items (but also single items because of implicit cast)
public static void WriteLine(params Item[][] items)
{
Console.WriteLine(string.Join(", ", items.SelectMany(x => x)));
}
}
public class Test
{
public void Main()
{
var array = new[] { new Item("a1"), new Item("a2"), new Item("a3") };
Print.WriteLine(new Item("one"), /* ... */ array, new Item("two"));
}
}
there is no direct pre-built library in C# to handle what is built into Spread
In order to get that functionality in C#, you need to Reflect the object and get the methods, properties, or fields by their access modifiers.
You'd do something like:
var tempMethods = typeof(myClass).GetMethods();
var tempFields = typeof(myClass).GetFields();
var tempProperties = typeof(myClass).GetProperties();
then iterate through and throw them into your dynamic object:
using System;
using System.Collections.Generic;
using System.Dynamic;
namespace myApp
{
public class myClass
{
public string myProp { get; set; }
public string myField;
public string myFunction()
{
return "";
}
}
class Program
{
static void Main(string[] args)
{
var fields = typeof(myClass).GetFields();
dynamic EO = new ExpandoObject();
foreach (int i = 0; i < fields.Length; i++)
{
AddProperty(EO, "Language", "lang" + i);
Console.Write(EO.Language);
}
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
}
}
https://www.oreilly.com/learning/building-c-objects-dynamically
you can also do the following
var a = new List<int>(new int[]{1,2,3}){5};
Console.WriteLine(a.Count);
will print 4
if you want to achieve initialization of lists or arrays with both an accompanying enumerable and parameters

Get info about caller and parameters (name and value) of a Func<T> delegate

I have a class that expose a public method (ExecuteJob) that accept a Func delegate and run it asyncronusly. I need to know info about:
The Caller (class and method name that invoke ExecuteJob)
List of parameter and it's value used to call Func delegate
If it's possible, before run Func delegate, set value of specific parameter of this delegate
Example Code
public static class JobHandlerManager
{
public static async Task ExecuteJob<T>(Func<T> MetodoDaEseguire)
{
Params parOfMethod = MetodoDaEseguire.GetMethodParams();
// here I need to get info about above points
string Caller = "ExternalMethod"
string Parameters = "\"par1\" = \"a\", \"par2\" = 10, \"par3\" = [\"x\", \"y\", \"z\"] "
int JobID = CalculateJobId();
parOfMethod = parOfMetho.add(JobID);
Func<T> NewMethod = MetodoDaEseguire(parOfMethod);
Task.Run(MetodoDaEseguire);
}
}
public void DoStuff(string par1, int par 2, string[] arraypar, int JobID)
{
// JobID is set by JobHandlerManager.ExecuteJob
}
public void ExternalMethod()
{
JobHandlerManager.ExecuteJob(() => DoStuff("a", 10, new string[] {"x", "y", "z"}));
}
In provided case you can achieve at least parts of this using expression trees and CallerMemberNameAttribute:
public static int DoStuff(string par1, int par2, string[] arraypar, int JobID)
{
// JobID is set by JobHandlerManager.ExecuteJob
return 1;
}
public static void ExternalMethod()
{
JobHandlerManager.ExecuteJob(() => DoStuff("a", 10, new string[] { "x", "y", "z" },1));
}
public static class JobHandlerManager
{
public static T ExecuteJob<T>(Expression<Func<T>> MetodoDaEseguire, [CallerMemberName]string caller = "")
{
Console.WriteLine(caller); // will print "ExternalMethod"
var mc = MetodoDaEseguire.Body as MethodCallExpression;
Console.WriteLine(string.Join(", ", mc.Method.GetParameters().Select(p => p.Name))); // will print "par1, par2, arraypar, JobID"
Console.WriteLine(string.Join(", ", mc.Arguments)); // will print ""a", 10, new [] {"x", "y", "z"}, 1"
return MetodoDaEseguire.Compile()();
}
}
And calling ExternalMethod(); will print:
ExternalMethod
par1, par2, arraypar, JobID
"a", 10, new [] {"x", "y", "z"}, 1
But beware of performance and closures (i.e. to get actual values passed from local variables, fields, etc. more work will be needed to be done).
To get caller class you can try to look into Environment.StackTrace or CallerFilePathAttribute for example (depends on your needs).
UPD
To replace some of the arguments you can do something like this:
var newArgs = mc.Arguments.ToList();
var ardIdToReplace = newArgs.Count - 1; // find somehow index of replaced argument
newArgs[ardIdToReplace] = Expression.Constant(42);
var newLambda = Expression.Lambda<Func<T>>(Expression.Call(mc.Method, newArgs));
return newLambda.Compile()();
Bear in mind this also can be quite error prone cause due to custom handling of expression you loose a lot of compile time safety (user can pass a lot of more then my solution can support).
I found by my self a solution form my last problem, including this two method inside ma static class.
private static object GetArgumentValue(Expression element)
{
if (element is ConstantExpression)
{
return (element as ConstantExpression).Value;
}
var l = Expression.Lambda(Expression.Convert(element, element.Type));
return l.Compile().DynamicInvoke();
}
private static string[] GetParamArgumentsValue(ReadOnlyCollection<Expression> Arguments)
{
List<string> ParamArgumentsValue = new List<string>();
foreach (var arg in Arguments)
{
ParamArgumentsValue.Add(JsonConvert.SerializeObject(GetArgumentValue(arg)));
}
return ParamArgumentsValue.ToArray();
}

C# js-like spread (or triple dot) operator [duplicate]

Is there any implementation in C# like JavaScript's spread syntax?
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(...arr);
There isn't a spread option. And there are reasons.
Method Parameters aren't an array in C# unless you use the params keyword
Method Parameters that use the param keyword would have to either:
Share the same type
Have a castable shared type such as double for numerics
Be of type object[] (as object is the root type of everything)
However, having said that, you can get similar functionality with various language features.
Answering your example:
C#
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(string.Join(", ", arr));
The link you provide has this example:
Javascript Spread
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
Params
In C#, with same type
public int Sum(params int[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new int[] {1,2,3};
Console.WriteLine(Sum(numbers));
In C#, with different numeric types, using double
public int Sum(params double[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new double[] {1.5, 2.0, 3.0}; // Double usually doesn't have precision issues with small whole numbers
Console.WriteLine(Sum(numbers));
Reflection
In C#, with different numeric types, using object and reflection, this is probably the closest to what you are asking for.
using System;
using System.Reflection;
namespace ReflectionExample
{
class Program
{
static void Main(string[] args)
{
var paramSet = new object[] { 1, 2.0, 3L };
var mi = typeof(Program).GetMethod("Sum", BindingFlags.Public | BindingFlags.Static);
Console.WriteLine(mi.Invoke(null, paramSet));
}
public static int Sum(int x, double y, long z)
{
return x + (int)y + (int)z;
}
}
}
One trick to get a behavior similar to this (without reflection) is to accept params SomeObject[][] and to also define an implicit operator from SomeObject to SomeObject[]. Now you can pass a mixture of arrays of SomeObject and individual SomeObject elements.
public class Item
{
public string Text { get; }
public Item (string text)
{
this.Text = text;
}
public static implicit operator Item[] (Item one) => new[] { one };
}
public class Print
{
// Accept a params of arrays of items (but also single items because of implicit cast)
public static void WriteLine(params Item[][] items)
{
Console.WriteLine(string.Join(", ", items.SelectMany(x => x)));
}
}
public class Test
{
public void Main()
{
var array = new[] { new Item("a1"), new Item("a2"), new Item("a3") };
Print.WriteLine(new Item("one"), /* ... */ array, new Item("two"));
}
}
there is no direct pre-built library in C# to handle what is built into Spread
In order to get that functionality in C#, you need to Reflect the object and get the methods, properties, or fields by their access modifiers.
You'd do something like:
var tempMethods = typeof(myClass).GetMethods();
var tempFields = typeof(myClass).GetFields();
var tempProperties = typeof(myClass).GetProperties();
then iterate through and throw them into your dynamic object:
using System;
using System.Collections.Generic;
using System.Dynamic;
namespace myApp
{
public class myClass
{
public string myProp { get; set; }
public string myField;
public string myFunction()
{
return "";
}
}
class Program
{
static void Main(string[] args)
{
var fields = typeof(myClass).GetFields();
dynamic EO = new ExpandoObject();
foreach (int i = 0; i < fields.Length; i++)
{
AddProperty(EO, "Language", "lang" + i);
Console.Write(EO.Language);
}
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
}
}
https://www.oreilly.com/learning/building-c-objects-dynamically
you can also do the following
var a = new List<int>(new int[]{1,2,3}){5};
Console.WriteLine(a.Count);
will print 4
if you want to achieve initialization of lists or arrays with both an accompanying enumerable and parameters

Implement class to work with real time data

Using C# I need to transform a time series, for example:
Input: 1 2 1 0 3 2 -> Output: 1 3 4 4 7 9
In the previous example an output is the sum of current input with the previous inputs.
I will have different transformations so I started with an abstract class:
public abstract class Transformation<TInput, TOutput> {
private IEnumerable<TInput> _inputs { get; set; }
public Transformation(IEnumerable<TInput> inputs) {
_inputs = inputs;
}
public abstract IEnumerable<TOutput> Calculate();
}
So a transformation would be something like:
public class TransformationOne<Int32, Int32> {
public override IEnumerable<Int32> Calculate();
// Calculate the outputs with all inputs
}
}
This works fine if I have all inputs and want all outputs.
But sometimes I would like to use my class in real time.
So I would feed with a new input and would get a new output.
What would be the best way to implement this?
Keep the state in the class and send the input to the Calculate method?
class TransformationOne
{
private int _currentResult;
public int Calculate(int value)
{
_currentResult += value;
return _currentResult;
}
}
so you could do:
var transformationOne = new TransformationOne();
var inputs = new List<int> {1, 2, 1, 0, 3, 2};
foreach (var input in inputs)
{
var newResult = transformationOne.Calculate(input);
Console.WriteLine(newResult); // results: 1 3 4 4 7 9
}
Demo
My answer is very similar to what #Julian did. However, I had already written my solution, I think it does a better job of providing the two aspects of the OP's question:
How to do this for a sequence of data (like what was originally shown)
How do use the same capability for one-at-a-time data
You can't easily do this with a generic, there is no way to constrain a type to one that includes addition (if you know of one, let me now). So this is what the transformation class looks like:
public class AccumulateTransformer
{
private int currentState = 0;
public void Clear()
{
currentState = default(int);
}
public int NextValue(int input)
{
currentState += input;
return currentState;
}
public int Current => currentState;
public IEnumerable<int> TransformSequence(IEnumerable<int> inputs, bool clearFirst = true)
{
if (clearFirst)
{
Clear();
}
foreach (var value in inputs)
{
yield return NextValue(value);
}
}
}
And here's some code to test it (using your data):
var transformer = new AccumulateTransformer();
var inputs = new[] {1, 2, 1, 0, 3, 2,};
var results = transformer.TransformSequence(inputs);
Debug.WriteLine(string.Join(", ", from result in results select result.ToString() ));
transformer.Clear();
Debug.WriteLine(transformer.NextValue(1));
Debug.WriteLine(transformer.NextValue(2));
Debug.WriteLine(transformer.NextValue(1));
Debug.WriteLine(transformer.NextValue(0));
Debug.WriteLine(transformer.NextValue(3));
Debug.WriteLine(transformer.NextValue(2));
The output of that looks like:
1, 3, 4, 4, 7, 9
1
3
4
4
7
9
To make this generic, you need a way of doing the accumulation operation that isn't dependent on T understanding addition. To do that, change the code to what's show below.
It makes the type generic on T (which would be int in this case), but includes a constructor that takes a Func<T, T, T> that will do the accumulation. When you construct your instance, you provide a Func that just adds two numbers.
The class code:
public class AccumulateTransformer<T>
{
private T _currentState = default(T);
private Func<T, T, T> _accumulator;
public AccumulateTransformer(Func<T, T, T> accumulator)
{
_accumulator = accumulator;
}
public void Clear()
{
_currentState = default(T);
}
public T NextValue(T input)
{
_currentState = _accumulator(_currentState, input);
return _currentState;
}
public T Current => _currentState;
public IEnumerable<T> TransformSequence(IEnumerable<T> inputs, bool clearFirst = true)
{
if (clearFirst)
{
Clear();
}
foreach (var value in inputs)
{
yield return NextValue(value);
}
}
The only difference in using this is that you have to provide that accumulate Func in the constructor:
var transformer = new AccumulateTransformer<int>((a, b) => a + b);
Otherwise, it's used the same way and produces the same output.
I'm not sure if this is exactly what you're after, but you could simply keep a list of the items in the class, and provide public methods for adding new items to it:
public class Transformer
{
private readonly List<int> items = new List<int>();
public IEnumerable<int> Items => items.ToList();
public void Add(int item) => items.Add(items.LastOrDefault() + item);
public void Add(IEnumerable<int> input)
{
foreach (var item in input) Add(item);
}
public override string ToString()
{
return string.Join(", ", Items);
}
}
In use it might look like:
public static void Main(string[] args)
{
var trans = new Transformer();
var items = new[] { 1, 2, 1, 0, 3 };
// Add a bunch of inputs at once:
trans.Add(items);
// Display results
Console.WriteLine($"After adding 5 items: {trans}");
// Add a single item
trans.Add(2);
// Display results
Console.WriteLine($"After adding 1 more item: {trans}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
A simple Linq.Select() would do that:
int sum = 0;
var result = input.Select(x => { sum += x; return sum; });
Live Demo

Having a C# method return more than one value of different data types?

I have a function which takes two parameters:
string[], double[]
How do I return both of these values? How do call that function?
Hey you can use the keyword "out":
column s1;
column s2;
public void method1(out value1, out value2)
{
select col1, col2, from tb1
value1 = col1;
value2 = col2;
}
Create an object with properties for the values you want to return:
public class MyReturnType
{
public string[] MyStringArray { get; set; }
public double[] MyDoubleArray { get; set; }
}
Your method would then return this new type:
public MyReturnType Foo()
{
...
return new MyReturnType { MyStringArray = strings; MyDoubleArray = doubles; };
}
Use a Tuple structure (new in .NET 4.0, but you can just make one up in your own dll based on it - it is a simple container for multiple generic types).
Use a specialized carrier structure like Michael Shimmins answer says, but make it a struct, not a class, unless it is large.
Use a dicitonary or an array of object, if that is a purely internal function (case issues).
Use out parameters.
You can use the out or ref parameter.
See here and here
you cant return this directly but you can return this using strct. you can create struct for string and double and store the value in it,after that you can return it.
you can also use ref operator
You could return a Hashtable of objects. Or a List... or any sort of object collection you want.
LE:
Hashtable process(string[] x, double[] y)
{
Hashtable output = new Hashtable();
// do whatever you want with x and y
output["stringArray"] = x;
output["doubleArray"] = y;
return output;
}
// ...
string[] stringArray = new string[] {};
double[] doubleArray = new double[] {};
// ...
Hashtable outcome = process(stringArray, doubleArray);
string[] data1 = (string[])outcome["stringArray"];
double[] data2 = (double[])outcome["doubleArray"];
// ...

Categories