How to skip optional parameters in C#? - c#

Example:
public int foo(int x, int optionalY = 1, int optionalZ = 2) { ... }
I'd like to call it like this:
int returnVal = foo(5,,8);
In other words, I want to provide x and z, but I want to use the default for Y, optionalY = 1.
Visual Studio does not like the ,,
Please help.

If this is C# 4.0, you can use named arguments feature:
foo(x: 5, optionalZ: 8);
See this blog for more information.

In C# 4.0 you can name the arguments occurring after skipped defaults like this:
int returnVal = foo(5, optionalZ: 8);
This is called as named arguments. Several others languages provide this feature, and it's common form them to use the syntax foo(5, optionalZ=8) instead, which is useful to know when reading code in other languages.

Another dynamic way to supply parameters of your choise is to implement your method(s) in a class and supply named parameters to the class constructor. Why not even add calls to methods on same line of code as mentioned here : How to define named Parameters C#
var p = new PersonInfo { Name = "Peter", Age = 15 }.BuildPerson();

This is a late answer, but for the people who get into this.
One could also use Overloads,that uses the same name as the method/function, but with a different set of parameters.
ea
int SummAll (int a=0, int b=1, int c=2)
{return a+b+c;}
int SumAll (int a=0;int c=10) //skipping B
{return a+c; }
This pattern equals how with intellicense we can browse through variations of functions.

Related

Function IIF, how to make it take 2N + 1 arguments of logical expressions?, C #

In Visual Basic, there is this IIF Function, as in Crystal Report, etc ...
In C # itself, this function does not exist, but it is the same as doing something like this:
bool a = true;
string b = a ? "is_True" : "is_False";
But for the code to be a bit easier to read I wanted to do it as a function for C #, leaving it like this:
public static T IIf<T>(bool expression, T truePart, T falsePart)
{
     return expression ? truePart : falsePart;
}
Or to not operate with the real values ​​can also be done using delegates, to access the necessary values:
public static T IIf<T>(bool expression, Func<T> truePart, Func<T> falsePart)
{
    return expression ? truePart() : falsePart();
}
So far this works well ...
But how can I modify this function so I can take 2N + 1 arguments?
(N - the number of logical expressions specified)
Example the desired result:
Each odd argument specifies a logical expression;
Each even argument specifies the value that is returned if the previous expression evaluates to true;
The last argument specifies the value that is returned if the previously evaluated logical expressions yielded false.
int value = IIf(Name = "Joel", 1, Name = "Peter", 2, Name = "Maria", 3, 4);
Can someone give me a hand with this?
Environment: C # - Visual Studio 2017
First off, as noted in the comments, this is a bad idea. Newer versions of C# already support pattern-matching switches as a built-in feature of the language; use it.
Second, this is a bad idea because the API of "argument, case1, result1, case2, result2, ..." has a signature that is hard to express in the C# type system.
Were I forced to implement such an API, I would suggest using tuples:
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases )
{
foreach(var c in cases)
if (item.Equals(c.Item1))
return c.Item2;
return theDefault;
}
Or, make a helpful utility method and use it:
public static T FirstOrDefault(
this IEnumerable<T> items,
T theDefault,
Func<T, bool> predicate)
{
foreach(var i in items.Where(predicate))
return i;
return theDefault;
}
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases ) =>
cases.FirstOrDefault(
(item, theDefault),
c => item.Equals(c.Item1)).Item2;
If you cannot use tuples because you're using an older version of C#, you could make your own pair type or use the key-value pair type.
But just do not go there. If you need a switch, write a switch. If you need a dictionary, write a dictionary.
If you want to preserve the order of your parameters, which presumably you do if you're trying so hard to make the function replicate what you've seen elsewhere, then you can write something like this:
public T IIf<T>(params object[] objects) {
for(var i = 0; i < objects.Length - 1; i += 2)
if((bool)objects[i])
return (T)objects[i+1];
return (T)objects[objects.Length - 1];
}
But it's a good lesson in why you would avoid something like this. Firstly, you have to explicitly declare the type you're working with. So you'd have to use it like this:
var value = IIf<int>(Name == "Joel", 1, Name == "Peter", 2, Name == "Maria", 3, 4);
Notice the passing of 'int' as a type parameter. You can avoid that by changing the order of the parameters so that the default comes first.
But, if you're just willing to adopt a personal pattern, the nested ternary syntax can be quite readable:
var value =
Name == "Joel" ? 1
: Name == "Peter" ? 2
: Name == "Maria" ? 3
: 4;
If you don't feel it's readable, then it's just because it takes some getting used to. Imagine going the other way, from a C# developer to VB, and seeing 'IIF'. You'd be thinking, "why do they add the extra 'I' in 'IF'?". I should make a function "IF" that emulates "IIF". But that would be a bad idea, wouldn't it?

C# Split String and Assign Splitted Value To Another Variable

I am trying to split a string and assign the different values. The string it returns to me is:
0077|PCK|PRD|05025066840471|4|Can Opener|1|10|B|20.00|0|100|0|0.00|0|0|1|0|0
So I want to split the string on "|" and assign each of them to another variable. That is what I tried to do:
public static void LoadPRD(string sData)
{
string[] s = null;
prdType PRD = new prdType();
s = sData.Split("|");
PRD.bCode = s.Left(s[0], 14);
PRD.PCode = s.Left(s[1], 12);
PRD.Desc = s.Left(s[2], 40);
PRD.Pack = s.Val(s[3]);
PRD.Unit = s.Left(s[4], 12);
PRD.VATCode = s.Left(s[5], 1);
PRD.VATRate = Conversion.Val(s[6]);
PRD.Cost = Conversion.Val(s[7]);
PRD.Sell = Conversion.Val(s[8]);
PRD.Stock = Conversion.Val(s[9]);
PRD.AWS = Conversion.Val(s[10]);
PRD.OnOrder = Conversion.Val(s[11]);
PRD.OrderQty = Conversion.Val(s[12]);
PRD.LabelQty = Conversion.Val(s[13]);
PRD.Restriction = s.Left(s[14], 1);
PRD.MinStock = s.Val(s[15]);
PRD.PromoCode = s.Left(s[16], 3);
PRD.MnM = s.Left(s[17], 3);
}
The error message says that the Strings does not exist in the context, but it is not too of a helpful information, I do understand what it means but I am very confused on how to approach the solution.
Just so you know, I did create the variable before hand, I've posted them below:
public struct prdType
{
public string bCode;
public string PCode;
public string Desc;
public Int16 Pack;
public string Unit;
public string VATCode;
public float VATRate;
// Stored in pence
public long Cost;
public long Sell;
public long Stock;
public float AWS;
public long OnOrder;
public long OrderQty;
public long LabelQty;
public string Restriction;
public long MinStock;
public string PromoCode;
}
Your help will be much appreciated.
Thanks.
EDIT:
On
s = sData.Split("|");
it says: "The best overloaded method match for string.Split(params char[]) has some invalid arguments. It also says that arguments cannot be converted to char. Any ideas?
Rather than use legacy VB methods for this, I would suggest using C# methods all the way.
string[] s = sData.Split('|');
The use of Strings.Left is not readily apparent. Since you've already split the line, you'll have each element of the split in its entirety. If you want to take only the first n characters, you can do that, but there is no built-in equivalent for Strings.Left in C#.
For those elements that are a different type, you can use Convert.ToX:
PRD.Pack = Convert.ToInt16(s[3]));
PRD.VATRate = Convert.ToSingle(s[6]));
PRD.Cost = Convert.ToInt64(s[7]);
And so on. Note that float uses Convert.ToSingle, not Convert.ToFloat.
ADDED
Based on #Raphael's comment, Convert.ToX is not a direct replacement for Conversion.Val(), but as long as the string is strictly numeric you will be ok and will get the correct type.
These methods come from Microsoft.VisualBasic namespace.It should be only used if you know what you're doing (see Tim's comment on this answer).
I wouldn't advise you to use these methods.
They are equivalent methods in c# (or they're rather easy to implement).
Like String.Split, for example (so you could do var s = sData.Split('|'); )
A way to do something equivalent to String.Left
Wouldn't advise to do this, but anyway :
If you want absolutely use them, you should :
Add a reference to Microsoft.VisualBasic assembly (right click on project's references, you should find it in Framework libs)
Add the right using at the top of your code : using Microfost.VisualBasic;
You need to do s = sData.Split('|');

Create an object ArrayList from a class

I want to know if is possible in Visual Studio 2005 C++ to create an ArrayList of objects of a class.
I will have this class:
class var
{
int x;
int y;
}
In C# is something like this: ArrayList<var> list = new ArrayList<var>(); , but in C++ doesn't work.
I forgot to mention that the project is a Windows Form Application.
Have you tried std::vector<var> myVector or std::list<var> myList?
That should do the job:
#include <vector>
using std::vector;
class var
{
int x;
int y;
};
int main(void)
{
vector<var> myVec(10); // creates a vector of 10 elements of var objects
// ... other stuff
return 0;
}
But there are many more ways to put objects into a vector, e.g. create an empty vector and using vector::push_back(), etc. You should read the Standard libs' documentation for all the alternatives.
You can do this:
var myArray[50];
Which are 50 vars on the stack. You can also do this:
var* myArray = new var[50];
Which are 50 vars on the heap. Or you could just use a std::vector:
var myObject;
std::vector <var> myVector;
myVector.push_back(var);
Or, the last one that I usually use is:
std::vector <var*> myVector;
var* pVar = new var();
myVector.push_back(pVar);
There are way too many ways of doing it, these are just a few.

Why can't we give names to properties in Tuples?

Is there a specific reason that we have to refer to the properties in a Tuple as Item1, Item2 etc. This just seems like a bad idea to me as they could easily get mixed up in your code. Wouldn't it be much more meaningful to be able to name your properties ie. Red, Green, Blue?
If you want names, don't use Tuples.
Anonymous type:
var t = new { Green = 1, Red = "nice" };
if (t.Green > 0) ....
The Tuple<...> classes are just normal C# classes. C# does not provide a way to have dynamically-named properties (aside from just using a Dictionary or a dynamic object like ExpandoObject). However, C# does provide something like what you want via anonymous types:
var x = new { Red = 10, Blue = 20, Green = 30 }
var sum = x.Red + x.Blue + x.Green;
The reason anonymous types work is that they are just a convenient syntax for defining a custom tuple class on the fly.
These have the advantage of acting like named tuples, but have the disadvantage of not being nameable by the programmer (so you can't make a method that explicitly returns an anonymous type).
If you want to do this then create a class with the appropriately named properties. A tuple is just a quick and dirty way of avoiding having to write a class or use out params when you want to return multiple values from a method.
A tuple is not supposed to contain any meaningful properties. It is just a disposable set of items bunched together in a group.
If you want meaningful property names, make a type with those properties. You can either write a class from scratch and use that class, or use anonymous types.
You could define the class like this (with generics) if you will always be partial to Red/Blue, otherwise, you can use anonymous types as suggested by others.
class RedBluePair<T1, T2>
{
private T1 _Red;
private T2 _Blue;
public RedBluePair(T1 red, T2 blue)
{
_Red = red;
_Blue = blue;
}
public T1 Red { get { return _Red;} }
public T2 Blue { get { return _Blue;} }
}
Reproducing my answer from this post as now it is possible to give names to properties in Tuples.
Starting C# v7.0 now it is possible to name the tuple properties which earlier used to default to names like Item1, Item2 and so on.
Naming the properties of Tuple Literals:
var myDetails = (MyName: "RBT_Yoga", MyAge: 22, MyFavoriteFood: "Dosa");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");
The output on console:
Name - RBT_Yoga, Age - 22, Passion - Dosa
Returning Tuple (having named properties) from a method:
static void Main(string[] args)
{
var empInfo = GetEmpInfo();
Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}
static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
//This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
return ("Rasik", "Bihari", "Rasik-PC", 1000);
}
The output on console:
Employee Details: Rasik, Bihari, Rasik-PC, 1000
Creating a list of Tuples having named properties
var tupleList = new List<(int Index, string Name)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
foreach (var tuple in tupleList)
Console.WriteLine($"{tuple.Index} - {tuple.Name}");
Output on console:
1 - cow
5 - chickens
1 - airplane
I hope I've covered everything. In case, there is anything which I've missed then please give me a feedback in comments.
Note: My code snippets are using string interpolation feature of C# v7 as detailed here.
Yes, You can name tuple properties from C# 7.0.
From this documentation,
You can explicitly specify the names of tuple fields either in a tuple initialization expression or in the definition of a tuple type, as the following example shows:
(int Red, int Green, int Blue) ColorRGB = (0, 0, 255);
// Or
var ColorRGB = (Red: 0, Green: 0, Blue: 255);
Or,
If you don't specify a field name, it may be inferred from the name of the corresponding variable in a tuple initialization expression, as the following example shows:
int Red = 0;
int Green = 0;
int Blue = 255;
var ColorRGB = (Red, Green, Blue);

Is there a class in C# to handle a couple of INT (range of 2 INT- 1-10)

I am quite new to C# and I was wondering if there is a Class or a data structure or the best way to handle the following requirement...
I need to handle a COUPLE of int that represent a range of data (eg. 1 - 10 or 5-245) and I need a method to verify if an Int value is contained in the range...
I believe that in C# there is a class built in the framework to handle my requirement...
what I need to do is to verify if an INT (eg. 5) is contained in the range of values Eg (1-10) ...
in the case that I should discover that there is not a class to handle it, I was thinking to go with a Struct that contain the 2 numbers and make my own Contain method to test if 5 is contained in the range 1-10)
in the case that I should discover that there is not a class to handle
it, I was thinking to go with a Struct that contain the 2 numbers and
make my own Contain method to test if 5 is contained in the range
1-10)
That's actually a great idea as there's no built-in class for your scenario in the BCL.
You're looking for a range type; the .Net framework does not include one.
You should make an immutable (!) Int32Range struct, as you suggested.
You may want to implement IEnumerable<int> to allow users to easily loop through the numbers in the range.
You need to decide whether each bound should be inclusive or exclusive.
[Start, End) is probably the most obvious choice.
Whatever you choose, you should document it clearly in the XML comments.
Nothing exists that meets your requirements exactly.
Assuming I understood you correctly, the class is pretty simple to write.
class Range
{
public int Low {get; set;}
public int High {get; set;}
public bool InRange(int val) { return val >= Low && val <= High; }
}
A Tuple<int,int> would get you part of the way but you'd have to add an extension method to get the extra behavior. The downside is that the lower- and upper-bounds are implicitly Item1 and Item2 which could be confusing.
// written off-the-cuff, may not compile
public static class TupleExtension
{
public static bool InRange(Tuple<int, int> this, int queryFor)
{
return this.Item1 >= queryFor && this.Item2 <= queryFor;
}
}
You could create an extension if you want to avoid making a new type:
public static class Extensions
{
public static bool IsInRange(this int value, int min, int max)
{
return value >= min && value <= max;
}
}
Then you could do something like:
if(!value.IsInRange(5, 545))
throw new Exception("Value is out of range.");
i think you can do that with an array.
some nice examples and explanation can be found here:
http://www.dotnetperls.com/int-array
Nothing built in AFAIK, but (depending on the size of the range) an Enumerable.Range would work (but be less than optimal, as you're really storing every value in the range, not just the endpoints). It does allow you to use the LINQ methods (including Enumerable.Contains), though - which may come in handy.
const int START = 5;
const int END = 245;
var r = Enumerable.Range(START, (END - START)); // 2nd param is # of integers
return r.Contains(100);
Personally, I'd probably go ahead and write the class, since it's fairly simple (and you can always expose an IEnumerable<int> iterator via Enumerable.Range if you want to do LINQ over it)

Categories

Resources