That is the question.
Background: C# Params
In C#, you can declare the last parameter in a method / function as 'params', which must be a single-dimension array, e.g.:
public void SomeMethod(int fixedParam, params string[] variableParams)
{
if (variableParams != null)
{
foreach(var item in variableParams)
{
Console.WriteLine(item);
}
}
}
This then essentially allows syntactic sugar at the call site to implicitly build an array of zero or more elements:
SomeMethod(1234); // << Zero variableParams
SomeMethod(1234, "Foo", "Bar", "Baz"); // << 3 variableParams
It is however still permissable to bypass the sugar and pass an array explicitly:
SomeMethod(1234, new []{"Foo", "Bar", "Baz"});
Yes. In standard C++, you can use va_arg and the ... syntax. See MSDN for details.
For C++/CLI, There is a shortcut for this.
You do this as:
void TheMethod( String^ firstArgument, ... array<Object^>^ variableArgs );
See this blog post for details.
For unmanaged C++ with the same convenient syntax, no.
But there is support for variable argument lists to functions in C++.
Basically you declare a function with the last parameter being an ellipsis (...), and within the body of the function use the va_start()/va_arg() calls to parse out the supplied parameter list.
This mechanism is not type safe, and the caller could pass anything, so you should clearly document the public interface of the function and what you expect to be passed in.
For managed C++ code, see Reed's comments.
Nowadays, with modern C++, you can use modern type-safe practices for variadic functions.
Use either variadic templates or std::initializer_list if all your arguments have the same type
With variadic template, you use recursion to go through a variadic parameter list. Variadic template example:
template<class T>
void MyFoo(T arg)
{
DoSomething(arg);
}
template<class T, class... R>
void MyFoo(T arg, R... rest)
{
DoSomething(arg);
// If "rest" only has one argument, it will call the above function
// Otherwise, it will call this function again, with the first argument
// from "rest" becoming "arg"
MyFoo(rest...);
}
int main()
{
MyFoo(2, 5.f, 'a');
}
This guarantees that if DoSomething, or any other code you run before the recursive call to MyFoo, has an overload for the type of each argument you pass to the function MyFoo, that exact overload will get called.
With std::initializer_list, you use a simple foreach loop to go through the arguments
template<class T>
void MyFoo(std::initializer_list<T> args)
{
for(auto&& arg : args)
{
DoSomething(arg);
}
}
int main()
{
MyFoo({2, 4, 5, 8, 1, 0}); // All the arguments have to have the same type
}
Yes! C++11 and above allows function templates to take a type-safe variable number of arguments, creating what's known as a "parameter pack". You can unpack that into, e.g., a std::array and get something a lot like you are looking for:
struct S {
template <typename... Args>
void SomeMethod(int someParam, Args&&... args) const {
//^ The "&&" here is a "forwarding reference" because Args is a template.
// Next line isn't required but arguably helps with error messages:
static_assert((std::is_convertible_v<Args, std::string_view> && ...), "All args in the pack must convert to string_view.");
// Convert args... to a std::array<std::string_view, N>:
const auto variableParams = std::array<std::string_view, sizeof...(args)>{std::forward<Args>(args)...};
if (not variableParams.empty()) { //< Not needed because it's a nop to iterate over an empty array:
for (const auto& item : variableParams) {
fmt::print("{}\n", item);
}
}
}
};
int main() {
S s;
s.SomeMethod(42, "foo", "bar", "baz");
}
output:
foo
bar
baz
https://godbolt.org/z/PbPb7qTv9
In C++20, you can use concepts to get a better error message and to be more concise:
void SomeMethod(int someParam,
std::convertible_to<std::string_view> auto&&... args) const {
Happy case: https://godbolt.org/z/aTG74Wx7j
Error case: https://godbolt.org/z/jToxYMThs
There is a named parameters library in boost (if I understood correctly what params in C# are). It allows writing functions like this:
int y = lib::f(_name = "bob", _index = 2);
Can't tell anything about if there is a significant overhead involved.
Related
I was translating some C++ code to C# and there was a function pointer within a structure definition, say func*
This func* was a pointer to a lot of other function pointers all contained within a C++ header file (This header file won't be translated).
Is there a way to translate this?
Code snippet:
struct CK_FUNCTION_LIST {
int version;
/* Pile all the function pointers into it. */
#include "pkcs11f.h"
};
The class which I wish to translate contained a member of typeCK_FUNC_LIST*.
To demonstrate what you usually do when you want to use the equivalent of function pointers in C#, take a look at this:
struct MyFunctions {
public Func<int,string,bool> ptr1;
public Action<int> ptr2;
}
class Program
{
static void Main(string[] args)
{
MyFunctions sample = new MyFunctions() { ptr1 = TestValues, ptr2 = DoThing };
sample.ptr1(42, "Answer");
sample.ptr2(100);
}
static bool TestValues(int a, string b)
{
Console.WriteLine("{0} {1}", a, b);
return false;
}
static void DoThing(int a)
{
Console.WriteLine("{0}", a);
}
}
The output is:
42 Answer
100
If you are porting the code, you have a couple of options in C#:
1) Use lamdas (e.g. unnamed delegates). If these are 1-off functions (e.g. they are only used once), this will be the best choice.
2) Use named delegates. These will behave very similarly to C++ function pointers. If you are using the same functions in several places, this will be the better choice.
Just for clarification (as Ben Voigt pointed out): these are effectively the same thing as the lamda syntax will create a delegate for you.
The delegate type can be framework-provided (Action, Func, Predicate)
or user-declared, and the delegate can be created inline (lambda,
anonymous delegate) or by naming a method.
The normal way of using function pointers in C# is to declare an Action or Func. These are type safe, so they will only accept methods matching the signature of the type arguments.
Delegates are more generic (Action and Func are just specific named ones) but less clear. Really, we'd need more information to be any more specific.
Why does execute TestMethod<T>(params T[] input) method instead of execute TestMethod(object input).I am confusing why complier execute generic method.Is there any priority hierarchy on .net framework ?
class TestClass
{
static void Main()
{
TestMethod("Hello World");
}
static void TestMethod(object input)
{
Console.WriteLine("object");
}
static void TestMethod<T>(params T[] input)
{
Console.WriteLine("params T[]");
}
}
The comment on your question contains the link to the overload resolution specs of C# which contains all infos you need to answer the question in depth. It's not the most easy read, though and hard to find the actual path of resolution in your case, so here is what happens, as far as I can tell:
Parameter arrays:
First, we need to look at what the params keyword does: As it is a shortcut for the developers convenience, here is what it is identical to:
static void TestMethod<T>(params T[] input)
gets translated to
static void TestMethod<T>(T[] item)
and calls get translated accordingly:
TestMethod("string2", "string2");
gets translated to:
TestMethod(new string[] { "string1", "string2" );
Resolution:
With this in mind, let's see what the compiler does: The compiler evaluates its options to resolve your call at runtime.
Your call is:
TestMethod("string");
The first option is to translate this call to:
TestMethod(new string[] { "string" });
This would allow to call the generic version, while using string as T, which would result in the 'resolved method signature':
TestMethod(string[] item)
So, the required conversion from actual to required argument type is
string[] to string[]
Option b is to interpret the parameter "string" as what it is in our eyes, as a string. Then it would be feasible to call the non-generic version.
string to object
The conversions are evaluated according to section 7.4.3.4 of the C# spec and to avoid the downgrading of string to object, the first option is chosen.
this is because of overload resolution.
here is a good article
Similar Question:
Generic Overload Resolution
Often you want to send multiple values but due to low use (i.e. it is only used in one or two places), it's hard to justify creating a new type.
The Tuple<...> and KeyValuePair<,> type are very useful, but there isn't real language support for them.
Well sort of, a nice trick to use for Lists of tuples is to create a type that extends the List and adding a custom add method:
e.g.
public class TupleList<T1,T2> : List<Tuple<T1,T2>>{
public void Add(T1 key, T2 value){
base.Add(Tuple.Create(key, value));
}
}
This means that if I have a method that takes an IEnumerable<Tuple<int,string>>, I can use the following code to quickly build up the list like so::
Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}});
This makes winding values into a tuple list easier as we don't have to constantly keep saying Tuple.Create, and gets us almost to a nice functional languages syntax.
But when working with a tuple it is useful to unwind it out into its different components. This extension method might be useful in this respect::
public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2)
{
var1 = tuple.Item1;
var2 = tuple.Item2;
}
But even that's annoying as out parameters are not variant at all. That is if T1 is a string, I can't send in an object variable even though they are assignable, when as I can do the unwinding by hand otherwise. I can't really suggest a reason why you might want this variance, but if its there, I can't see why you would want to lose it.
Anyone have other tips to making working tuples, or tuple like objects easier in C#?
An important potential use for tuples might be generic memoization. Which is very easy in languages like F#, but hard in C#.
I'm currently using Tuples to supply a MethodBase and an array of tokens (constants, objects, or argument tokens), supplied to a dynamicly built object to construct certain member fields.
Since I wanted to make the syntax easier on API consumers, I created Add methods that can take a ConstructorInfo or a MethodInfo and a params array of objects.
Edit:
Eric Lippert as usual has excellent motivation for using Tuples here and he even says what I suspected there really is no support:
What requirement was the tuple designed to solve?
In C# you can alias closed generic types, which Tuple is, this enables you to provide some better insight to what is intended. Doesn't change code much, but if you look at the example below the intent of what GetTemp is returning is better.
Without alias:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static Tuple<double, string> GetTemp(double lat, double #long)
{
// just for example
return Tuple.Create(10d, "Mordor");
}
}
}
With alias:
namespace ConsoleApplication1
{
using CityTemp = Tuple<double, string>;
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static CityTemp GetTemp(double lat, double #long)
{
// just for example
return new CityTemp(10, "Mordor");
}
}
}
Use Mono! They have experimental support for binding variables to tuple members so you could call a method like
Tuple<string, string, string, int, string> ParseUri (string url);
using code like
(user, password, host, port, path) = ParseUri (url);
There will be an awesome tuple feature coming with c#7 / visual studio 15.
basically you can do soething like that
static (int x, int y) DoSomething()
{
return (1, 2);
}
static void Test()
{
var cool = DoSomething();
var value = cool.x;
}
Read according post
The following code sample prints:
T
T[]
T[]
While first two lines are as expected, why compiler selected param array for a regular array?
public class A
{
public void Print<T>(T t)
{
Console.WriteLine("T");
}
public void Print<T>(params T[] t)
{
Console.WriteLine("T[]");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Print("string");
a.Print("string","string");
a.Print(new string[] {"a","b"});
}
}
Under the hood
a.Print("string","string");
is just syntactic sugar for
a.Print(new string[]{"string","string"});
EDIT: Like I said, the params keyword only automagically creates the array for you, you tell the compiler: either accept an array of T directly or use the X input params to construct that array.
It addition to what others have said, the params keyword also causes a ParamArrayAttribute to the generated for array parameter. So, this...
public void Print<T>(params T[] t) { }
Is generated by the compiler as...
public void Print<T>([ParamArray] T[] t); { }
It is that attribute which indicates to the compiler and the IDE that the method can be called using simpler syntax...
a.Print("string", "string");
rather than...
a.Print(new string[] { "string", "string" });
I think this actually has more to do with type inference than with the params keyword. The inference engine assumes on the third line that the type of T is string[] and therefore passes it to the first method.
try Console.WriteLine(typeof(T)) if you don't believe me
when having the params keyword, the compiler will do a little bit of translation for the formal function declaration, as well as the actual function call.
Formal function declaration:
Under the hood, the IL will be translated to essentially the same as
public void Print<T>(T[] array);
Except, when compiling, the actual function call will be checked for syntax translation. Meaning,
a.Print("string1", "string2");
Becomes the same IL code as
a.Print(new string[]{"string1", "string2"});
That is why line 2 and 3 are the same output, because under the hood, they got translated to the exact same IL.
Question about why line 3 is not print "T" is because, .NET compiler will always try to find the best overloaded match, and so both line 2 and 3 called to the T[] version instead of the plain T.
Exactly as arul said. If you open up the project in reflector, you'll see the following:
a.Print<string>(new string[] { "string", "string" });
Params allows you to pass multiple objects of the same type. it is a shortcut way of passing array
If you go right now and type string.Format into your IDE, you'll see that there are 4 different overloads: one taking a string and object, another taking a string and two objects, then one taking three objects, and finally one that uses params. According to this answer, this is because params generates 'overhead', and some other languages may not support it.
My question is, why can't a method call like this:
void Foo()
{
Bar(1, 2, 3);
}
void Bar(params int[] args)
{
// use args...
}
Be essentially transformed at compile time to
void Foo()
{
Bar(new[] { 1, 2, 3 });
}
void Bar(int[] args)
{
// use args...
}
? Then it wouldn't create any overhead except for the array creation (which was necessary anyway), and would be fully compatible with other languages.
The number of arguments is already known at compile-time, so what's preventing the C# compiler from doing some kind of string substitution and making the first scenario essentially syntactic sugar for the second? Why did we have to implement hidden language features specifically to support variadic arguments?
The title makes an incorrect assumption.
Both a params and a non-params methods take an array; the difference is the compiler will emit the IL to create an array implicitly when making a params method call. An array is passed to both methods, as a single argument.
This can be seen in this .NET Fiddle (view "Tidy Up -> View IL").
using System;
public class Program
{
public static void Main()
{
var a1 = 1;
var a2 = 2;
var a3 = 3;
with_params(a1,a2,a3);
no_params(new [] {a1,a2,a3});
}
public static void with_params(params int[] x) {}
public static void no_params(int[] x) {}
}
In both cases the IL is identical; a new array is created, it is populated, and the array is supplied to the invoked method.
There is an "exception" to this identical IL generation in that the compiler can move out constant-valued arrays when used in the non-parameter form and use 'dup' initialization, as seen here. However, a new array is supplied as the argument in both cases.