How to create a linq extension method with Func<>? - c#

I've created extension methods that can be used like this:
string returnValue = numbers.At(separator, index).Slice();
But I want to create like this:
string returnValue = numbers.At(s => '.').Slice();
Here's the other code.
public class StringParameters
{
public string Text { get; set; }
public int Position { get; set; }
public StringParameters(string text, int position)
{
this.Text = text;
this.Position = position;
}
}
public static StringParameters At(this string text, char c)
{
int index = text.IndexOf(c);
if (index > 0)
{
int index2 = text.IndexOf(c, index + 1);
if (index2 > index)
{
text = text.Substring(index2, text.Length - index2);
}
return new StringParameters(text, index2 + 1);
}
return new StringParameters(null, -1);
}
public static string Slice(this StringParameters parameters)
{
return parameters.Text.Substring(parameters.Position);
}
Edit: I've edited the code and replaced ... with "something here". I do not still get the full idea what it should be there. My expectation is that the method should be more useful by this.
Edit 2: I have now an idea what I want to create with my code. I want to be able to make something like this:
string returnValue = numbers.At(s, i => GetStringParameter()).Slice();
Edit 3: I've edited the code a little bit. It will probably be more clearer now of what I want to achieve.
Edit 4: Corrected a mistake in the code above.

It is not clear for me what are you trying to achieve (start parameter, which you want to replace by function, is not used anywhere in At function), but here is an example extension function with Func<> parameter:
public static StringParameters At(this string text, char c, Func<int> startFunc)
{
int start = startFunc();
int index = text.IndexOf(c);
if (index > 0)
{
int index2 = text.IndexOf(c, index + 1);
if (index2 > index)
{
text = text.Substring(0, text.Length - index2);
}
return new StringParameters(text, index2 + 1);
}
return new StringParameters(null, -1);
}
Usage:
string returnValue = numbers.At(s, () => GetStartIndex()).Slice();
You don't need i => here until you have an argument that you will pass to the Func<> inside At function.
When you call int start = startFunc();, the function you passed as the parameter to At (GetStartIndex() in my example) will be called and its return value will be set to start variable.

I think you want
string returnValue = numbers.At(s, i => GetStringParameter()).Slice();
with the Slice extension method having a signature:
public static string Slice(this StringParameters parameters)
i.e. you want
StringParameters stringParameters = numbers.At(s, i => GetStringParameter());
string returnValue = stringParameters.Slice();
It sounds like you need an overload of your extension method, At, to have a signature like:
public static StringParameters At(this string text, S s, Func<T, U> func)
Where S is the type of the s you're passing in, T is the input to your Func, and U is the output type of the Func.
In the At method, you use your Func like you'd call a method, e.g.
Func<int, string> func = (int)i => i.ToString();
string s = func(123); // s == "123"

I have finally found the solution with the help of Aleksey Shubin and others. The final code looks like this:
public static class Linq
{
public class StringParameters
{
public string Text { get; set; }
public int Position { get; set; }
public StringParameters(string text, int position)
{
this.Text = text;
this.Position = position;
}
}
public static StringParameters At(this string text, Func<char> func)
{
char c = func();
int index = text.IndexOf(c);
if (index > 0)
{
int index2 = text.IndexOf(c, index + 1);
if (index2 > index)
{
text = text.Substring(index2, text.Length - index2);
}
return new StringParameters(text, index2 + 1);
}
return new StringParameters(null, -1);
}
public static string Cut(this StringParameters parameters)
{
return parameters.Text.Substring(parameters.Position);
}
}
This can be used like this:
string returnValue = "132.465..646.656.45".At(() => '.').Cut();
This returns the value of 6.45. It should return the value of 656.45 or probably 132.465, but this is pretty easy. Thanks everyone for your help.

Related

How to design a String class with MaxLength?

I am planning to create my own string class, but it will have a max length provided.
Let's call it "lString".
I want to use "lString" just like a "string" class in my code. But I will be able to set a maxlength for it.
For example, this code should be built:
// 1- No maxlength provided, so the object will be created.
lString mylString1 = "0123456789";
// 2- maxlength provided, so it will be checked, and then created.
lString mylString2 = new lString("0123456789", 10);
// 3- This time only maxlength provided, so it will be a string object with maxLength.
lString mylString3 = new lString(20);
// At the end, I should be able to use it like a regular strings:
mylString3 = mylString1 + mylString2;
// Below should throw exception at RunTime, because it will be over 20)
mylString3 = mylString1 + mylString2 + mylString1 + mylString2;
Its fairly trivial to implement a basic string class which has implicit operators to and from a normal string:
public class LimitedString
{
private readonly string value;
private readonly long maxLength;
public LimitedString(string value, long maxLength = long.MaxValue)
{
if(value != null && value.Length > maxLength)
throw new InvalidOperationException("Value is longer than max length");
this.value = value;
this.maxLength = maxLength;
}
public override string ToString()
{
return value;
}
public override int GetHashCode()
{
return value.GetHashCode();
}
public override bool Equals(object o)
{
if(o is LimitedString)
return value == ((LimitedString)o).value;
return false;
}
public static implicit operator LimitedString(string str)
{
return new LimitedString(str);
}
public static implicit operator String(LimitedString ls)
{
return ls.value;
}
}
And then your first 2 cases work as expected:
LimitedString myString1 = "0123456789";
LimitedString myString2 = new LimitedString("0123456789", 10);
However, the only way you can make your third example work is like this:
LimitedString myString3 = new LimitedString(myString1 + myString2 + myString1 + myString2, 20); // Throws exception
As once you re-assign the value your specification of the max length is lost, so you cant do this:
LimitedString myString3 = new LimitedString(20); // This is fine - you could have a constructor that just takes the max length.
myString3 = myString1 + myString2 + myString1 + myString2; // but here you're re-assigning.
Live example: https://rextester.com/KVBBQT19360

Using Indexers for multiple Arrays in the class c#

I have two arrays in my Base class, and I want to create Indexers that can be used in both of them, attached below is an MVCE of what I am trying to do.
class Indexer
{
private string[] namelist = new string[size];
private char[] grades = new string[size];
static public int size = 10;
public IndexedNames() {
for (int i = 0; i < size; i++){
namelist[i] = "N. A.";
grades[i] = 'F';
}
}
public string this[int index] {
get {
string tmp;
if( index >= 0 && index <= size-1 ) {
tmp = namelist[index];
} else {
tmp = "";
}
return ( tmp );
}
set {
if( index >= 0 && index <= size-1 ) {
namelist[index] = value;
}
}
}
In the above coed if you comment out the lines private char[] grades = new string[size]; and grades[i] = 'F'; then you can use the indexers as object_name[i] but I want to be able to access both namelist and grades by indexers.
Note : I cannot use structures to wrap them together as in my application, there size may not always be same.
Is this possible or I would need to go around with some hack.
Edit
I am looking for something like names.namelist[i] and names.grades[i], or some statements that I can access them separately. Also Indexer logic is not consistent, and even size varies in some arrays, that was skipped here to aid simplicity in MVCE.
Sorry, no-can-do.
Although Indexers can be Overloaded and can have more than one formal parameter, you can't make two variations based on the same Parameter in the same class. This is a Language Limitation (or blessing).
Indexers (C# Programming Guide)
However, this should lead you to several options.
You can just make use of C#7. Ref returns
Starting with C# 7.0, C# supports reference return values (ref
returns). A reference return value allows a method to return a
reference to a variable, rather than a value, back to a caller. The
caller can then choose to treat the returned variable as if it were
returned by value or by reference. The caller can create a new
variable that is itself a reference to the returned value, called a
ref local.
public ref string Namelist(int position)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (position < 0 || position >= array.Length)
throw new ArgumentOutOfRangeException(nameof(position));
return ref array[position];
}
...
// Which allows you to do funky things like this, etc.
object.NameList(1) = "bob";
You could make sub/nested classes with indexers
That's to say, you could create a class that has the features you need with indexers, and make them properties of the main class. So you get something like you envisaged object.Namelist[0] and object.Grades[0].
Note : in this situation you could pass the arrays down as references and still access them in the main array like you do.
Example which includes both:
Given
public class GenericIndexer<T>
{
private T[] _array;
public GenericIndexer(T[] array)
{
_array = array;
}
public T this[int i]
{
get => _array[i];
set => _array[i] = value;
}
}
Class
public class Bobo
{
private int[] _ints = { 2, 3, 4, 5, 5 };
private string[] _strings = { "asd","asdd","sdf" };
public Bobo()
{
Strings = new GenericIndexer<string>(_strings);
Ints = new GenericIndexer<int>(_ints);
}
public GenericIndexer<string> Strings ;
public GenericIndexer<int> Ints ;
public void Test()
{
_ints[0] = 234;
}
public ref int DoInts(int pos) => ref _ints[pos];
public ref string DoStrings(int pos) => ref _strings[pos];
}
Usage:
var bobo = new Bobo();
bobo.Ints[1] = 234;
bobo.DoInts(1) = 42;
I think only a two parameter indexer can achieve what you want.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
class MyClass
{
protected static Dictionary<string, FieldInfo[]> table = new Dictionary<string, FieldInfo[]>();
static public int size = 10;
protected char[] grades = new char[size];
public object this[string name, int index]
{
get
{
var fieldInfos = table[this.GetType().FullName];
return ((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).GetValue(index);
}
set
{
var fieldInfos = table[this.GetType().FullName];
((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).SetValue(value, index);
}
}
static void Main()
{
var names = new MyChildClass();
names[DataColumns.Grades, 1] = 'S';
names[DataColumns.NameList, 9] = "W.S";
}
}
class MyChildClass : MyClass
{
private string[] namelist = new string[size];
static MyChildClass()
{
var t = typeof(MyChildClass);
table.Add(t.FullName, t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance));
}
public MyChildClass()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
grades[i] = 'F';
}
}
}
static class DataColumns
{
public static string NameList = "namelist";
public static string Grades = "grades";
}
}
Maybe something like this:
class Indexer
{
private string[] namelist = new string[size];
private string[] grades = new string[size + 1]; // size +1 to indicate different
// size
static public int size = 10;
public void IndexedNames()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
grades[i] = "F";
}
}
public string this[int i, int j]
{
get
{
string tmp;
// we need to return first array
if (i > 0)
{
tmp = namelist[i];
}
else
{
tmp = grades[i];
}
return (tmp);
}
set
{
if (i > 0)
{
namelist[i] = value;
}
else grades[i] = value;
}
}
}

C# - Finding key in an array by the value of its complex structure

is there a method in C# to find the key of the item in an array by its "subvalue"? Some hypothetical function "findKeyofCorrespondingItem()"?
struct Items
{
public string itemId;
public string itemName;
}
int len = 18;
Items[] items = new Items[len];
items[0].itemId = "684656";
items[1].itemId = "411666";
items[2].itemId = "125487";
items[3].itemId = "756562";
// ...
items[17].itemId = "256569";
int key = findKeyofCorrespondingItem(items,itemId,"125487"); // returns 2
You can use Array.FindIndex. See https://msdn.microsoft.com/en-us/library/03y7c6xy(v=vs.110).aspx
using System.Linq
...
Array.FindIndex(items, (e) => e.itemId == "125487"));
public static int findKeyofCorrespondingItem(Items[] items, string searchValue)
{
for (int i = 0; i < items.Length; i++)
{
if (items[i].itemId == searchValue)
{
return i;
}
}
return -1;
}
You can run a loop and check if itemId equal to the value you are searching for. Return -1 if no item matches with value.
Solution with Linq:
public static int findKeyofCorrespondingItem(Items[] items, string searchValue)
{
return Array.FindIndex(items, (e) => e.itemId == searchValue);
}

How, if possible, can you pass in a C# Property to be used like a method?

I know Func<> is used to pass a method that has a return value to be used inside another method. I know Action<> is used to pass a method that does not have a return value to be used inside another method. Is there a way to pass in a property so it's get/set can be used inside another method?
For example, here is a method that uses Func<>:
public bool RangeCheck (int minVal, int maxVal, Func<< int, int >> someMethod)
{
bool retval = true;
try
{
for (int count = min; count <= max; count++)
{
int hello = someMethod(count);
}
}
catch
{
retval = false;
}
return retval;
}
What I am looking for is something like this:
public bool RangeCheck(int min, int max, Prop<< int >> someProperty)
{
bool retval = true;
try
{
for (int count = min; count <= max; count++)
{
someProperty = count;
}
}
catch
{
retval = false;
}
return retval;
}
Is there anything out there like this? I can't find anything. This would be very useful. Thanks.
Could you use a lambda as a wrapper?
MyClass myClass = new MyClass();
bool val = RangeCheck(0, 10, () => myClass.MyProperty);
If you're looking to do both, you would make two lambdas, one for set, and one for get.
bool val = RangeCheck(0, 10, () => myClass.MyProperty, (y) => myClass.MyProperty = y);
My syntax is probably off, but I think this gives the idea.
Not that I know of. You could try using reflection and pass the object along with the corresponding PropertyInfo object of the property you want to get the value of. You then call PropertyInfo's SetValue function to assign a value to it (assuming it's read/write, of course).
public void SetMyIntValue()
{
SetPropertyValue(this, this.GetType().GetProperty("MyInt"));
}
public int MyInt { get; set; }
public void SetPropertyValue(object obj, PropertyInfo pInfo)
{
pInfo.SetValue(obj, 5);
}
Why not simply make it a ref argument?
public bool RangeCheck(int min, int max, ref int someProperty)
You can now set the value of someProperty inside the method.
And call it like so:
RangeCheck(min, max, ref myProperty);
You could use a Func like this Func<int, T>
void Main()
{
var sc = new SimpleClass();
var result = RangeCheck(0, 10, x => sc.Value = x );
System.Console.WriteLine(result);
System.Console.WriteLine(sc.Value);
}
public class SimpleClass
{
public int Value { get; set; }
}
public bool RangeCheck<T>(int minVal, int maxVal, Func<int, T> someMethod)
{
bool retval = true;
try
{
for (int count = minVal; count <= maxVal; count++)
{
//someMethod(count); //is not a range check,
//Did you mean
someMethod(count - minValue);
}
}
catch
{
retval = false;
}
return retval;
}

How to convert string type to user defined custom type

I have a string value that needs to be converted into my user defined custom type. how to do this, please help me.
public class ItemMaster
{
public static ItemMaster loadFromReader(string oReader)
{
return oReader;//here i am unable to convert into ItemMaster type
}
}
Depending on your type there are two ways that you could do it.
The first is adding a constructor to your type that takes a String parameter.
public YourCustomType(string data) {
// use data to populate the fields of your object
}
The second is adding a static Parse method.
public static YourCustomType Parse(string input) {
// parse the string into the parameters you need
return new YourCustomType(some, parameters);
}
Convert.ChangeType() method may help you.
string sAge = "23";
int iAge = (int)Convert.ChangeType(sAge, typeof(int));
string sDate = "01.01.2010";
DateTime dDate = (DateTime)Convert.ChangeType(sDate, typeof(DateTime));
Create a Parse method on your User Defined Custom type:
public class MyCustomType
{
public int A { get; private set; }
public int B { get; private set; }
public static MyCustomType Parse(string s)
{
// Manipulate s and construct a new instance of MyCustomType
var vals = s.Split(new char[] { '|' })
.Select(i => int.Parse(i))
.ToArray();
if(vals.Length != 2)
throw new FormatException("Invalid format.");
return new MyCustomType { A = vals[0], B = vals[1] };
}
}
Granted, the example provided is extremely simple but it at least will get you started.
First you need to define a format that your type will follow when being converted to a string.
A simple example is a social security number. You can easily describe it as a regular expression.
\d{3}-\d{2}-\d{4}
After that you simple need to reverse the process. The convention is to define a Parse method and a TryParse method for your type. The difference being that TryParse will not throw an exception.
public static SSN Parse(string input)
public static bool TryParse(string input, out SSN result)
Now the process you follow to actually parse the input string can be as complex or as simple as you wish. Typically you would tokenize the input string and perform syntactic validation. (EX: Can a dash go here?)
number
dash
number
dash
number
It really depends on how much work you want to put into it. Here is a basic example of how you might tokenize a string.
private static IEnumerable<Token> Tokenize(string input)
{
var startIndex = 0;
var endIndex = 0;
while (endIndex < input.Length)
{
if (char.IsDigit(input[endIndex]))
{
while (char.IsDigit(input[++endIndex]));
var value = input.SubString(startIndex, endIndex - startIndex);
yield return new Token(value, TokenType.Number);
}
else if (input[endIndex] == '-')
{
yield return new Token("-", TokenType.Dash);
}
else
{
yield return new Token(input[endIndex].ToString(), TokenType.Error);
}
startIndex = ++endIndex;
}
}
For the actual conversion, we would need to see the class structure for. The skeleton for this would look as follows however:
class MyType
{
// Implementation ...
public MyType ConvertFromString(string value)
{
// Convert this from the string into your type
}
}

Categories