Remove the static int from this MatchEvaluator - c#

I'm trying to convert a proprietary string mask to the .net equivalent of it.
For that I need to exchange every occurance of [someText] with {aDigit}.
private static int hits = 0;
private static object hitsLock = new object();
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString) {
Regex bracketsExpression = new Regex(#"\[[^[]*]");
lock (hitsLock)
{
hits = 0;
return bracketsExpression.Replace(sdsFileMaskString, ReplaceSquareWithAngularBrackets);
}
}
private static string ReplaceSquareWithAngularBrackets(Match m) {
string result = String.Format("{{{0}}}", hits.ToString());
hits++;
return result;
}
It works. But both expressions need to know each other's workings and are depending on the hits counter. I feel this could be improved. Ideally both have no dependency on each other. Any suggestions?
This can probably be done better. Any suggestions?

Yes - use an anonymous method or lambda expression:
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString, match =>
{
string result = String.Format("{{{0}}}", hits.ToString());
hits++;
return result;
});
}
This will capture the local variable in a new (compiler-generated) type, getting rid of the "globalness".
If you're happy with side-effects, you could make the lambda expression simpler, too. I'd also get rid of the call to String.Format in this case, as all those braces are confusing:
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString,
match => "{" + (hits++) + "}");
}

By using a lambda, and a local variable hits, C# will create a closure :
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString,
m => string.Format("{{{0}}}", hits++));
}
will be sufficient
The hits variable is encapsulated in the lambda closure and will be reused inside all lambda calls, but will be distinct for several ConvertSdsFileMaskToStringMask calls.

Related

substring out of range

I am trying to extract the number out of the last part of the string, I have wrote a function to do this but am having problems with out of range index.
Here is the string
type="value" cat=".1.3.6.1.4.1.26928.1.1.1.2.1.2.1.1" descCat=".1.3.6.1.4.1.26928.1.1.1.2.1.2.1.3"
and here is my function
private static string ExtractDescOID(string property)
{
string result = "";
int startPos = property.LastIndexOf("descOid=\"") + "descOid=\"".Length;
int endPos = property.Length - 1;
if (endPos - startPos != 1)
{
//This now gets rid of the first . within the string.
startPos++;
result = property.Substring(startPos, endPos);
}
else
{
result = "";
}
if (startPos == endPos)
{
Console.WriteLine("Something has gone wrong");
}
return result;
}
I want to be able to get 1.3.6.1.4.1.26928.1.1.1.2.1.2.1.3 this part of the string. I have stepped through the code, the string length is 99 however when AND MY startPos becomes 64 and endPos becomes 98 which is actually within the range.
The second argument to Substring(int, int) isn't the "end position", but the length of the substring to return.
result = property.Substring(startPos, endPos - startPos);
Read the documentation again, the second value is the length, not the index.
As found on MSDN:
public string Substring(
int startIndex,
int length
)
A different approach to this problem could be through using string.Split() to take care of the parsing for you. The only reason why I would propose this (other than that I like to present additional options to what's already there, plus this is the lazy man's way out) is that from a code perspective, the code is easier IMHO to decompose, and when decomposed, is easier to comprehend by others.
Here's the sample program with some comments to illustrate my point (tested, btw).
class Program
{
static void Main(string[] args)
{
var someAttributesFromAnXmlNodeIGuess =
"type=\"value\" cat=\".1.3.6.1.4.1.26928.1.1.1.2.1.2.1.1\" descCat=\".1.3.6.1.4.1.26928.1.1.1.2.1.2.1.3\"";
var descCat = GetMeTheAttrib(someAttributesFromAnXmlNodeIGuess, "descCat");
Console.WriteLine(descCat);
Console.ReadLine();
}
// making the slightly huge assumption that you may want to
// access other attribs in the string...
private static string GetMeTheAttrib(string attribLine, string attribName)
{
var parsedDictionary = ParseAttributes(attribLine);
if (parsedDictionary.ContainsKey(attribName))
{
return parsedDictionary[attribName];
}
return string.Empty;
}
// keeping the contracts simple -
// i could have used IDictionary, which might make sense
// if this code became LINQ'd one day
private static Dictionary<string, string> ParseAttributes(string attribLine)
{
var dictionaryToReturn = new Dictionary<string, string>();
var listOfPairs = attribLine.Split(' '); // items look like type=value, etc
foreach (var pair in listOfPairs)
{
var attribList = pair.Split('=');
// we were expecting a type=value pattern... if this doesn't match then let's ignore it
if (attribList.Count() != 2) continue;
dictionaryToReturn.Add(attribList[0], attribList[1]);
}
return dictionaryToReturn;
}
}

SortedList with string as index and function pointer or delegate as value? And Calling Functions by strings?

I'm not familiar with delegates and lambdas but at this moment, I have to do these two things:
One of them is:
I need to pass the function to SortedList. I don't know how it can be done.
Why I need it, is:
private string Func1(string s) { return s + "1"; }
private string Func2(string s) { return s + "2"; }
private string Func3(string s) { return s + "3"; }
private void WhatEver()
{
SortedList<string, ???> list = new SortedList<string, ???>;
list.Add("Func1", Func1);
list.Add("Func2", Func2);
list.Add("Func3", Func3);
// And after that I have to pass values and get results from functions
// Like
Console.WriteLine(list["Func1"]("Test"));
Console.WriteLine(list["Func2"]("Test"));
Console.WriteLine(list["Func3"]("Test"));
// Output should be:
//
// Test1
// Test2
// Test3
}
Second:
Is it possible to call functions with strings?
Ex:
Let's say I've got three textboxes and a function:
tbFunction
tbArgument
tbResult
private string Test(string number)
{
int x = int.Parse(number);
return (x * x).ToString();
}
Let's say I've got "Test" in tbFunction.Text and "2" in tbArgument.Text, How Can I bring the result to tbResult.Text
It took a while to figure out what you wanted. So, if I follow you correctly, you want:
Given the name of a method in a string variable, call than method.
The simple answer is that there is no intrinsic means of doing that. You could probably cobble together something using Reflection, but it would be more efforts than it's worth.
So, we'll need to create our own dispatch table:
// class member
var jumptbl = new SortedList<string, Func<string, string> >();
// : (in ctor)
jumptbl.Add("Test", Test);
// : (I'm guessing this is in a Click handler)
tbResult.Text = jumptbl[tbFunction.Text](tbArgument.Text)
Carrying this further, the name (in the string) used to call it need not have any connection to the name of the function itself. The method doesn't even have to have a name:
jumptbl.Add("Func1", s=> s + "1");
jumptbl.Add("Func2", s=> s + "2");
jumptbl.Add("Func3", s=> s + "3");
This is actually a job for reflection, has nothing to do with lambdas or delegates.
You will need to do something like...
MethodInfo method = typeof(ClassWithMethods).GetMethod(tbFunction.Text);
ClassWithMethods obj = new ClassWithMethods();
string result = method.Invoke(obj, new[] {tbArgument.Text});
tbResult.Text = result;
Check around in the System.Reflection documentation.
public delegate string YourDelegate(string number);
SortedList<string, YourDelegate> methods = new SortedList<string, YourDelegate>();
// Add more methods here
methods .Add("Test", Test);
...
public string CallMethod(string methodName, string number)
{
YourDelegate method;
if (methods.TryGetValue(methodName, out method))
return method(number);
else
return "Unknown method";
}
...
public void button1_Click(object sender, EventArgs e)
{
tbResult.Text = CallMethod(tbFunction.Text, tbArgument.Text);
}
I think that this is just about what you are asking for.
Personally I would use Dictinary but that is probably just a matter of taste.
Alternatively you could use reflection, that way you would not need to register each method in a list.

Please help me understand anonymous delegates?

I've downloaded the VCSharpSample pack from Microsoft and started reading on Anonymous Delegates. I can more or less understand what the code is doing, but I don't understand the reason behind it. Maybe if you gave me some examples where it would result in cleaner code and easier maintainability then I could wrap my head around it. :)
Can you help?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
delegate decimal CalculateBonus(decimal sales);
class Player
{
public string Name;
public decimal Score;
public decimal Bonus;
public CalculateBonus calculation_algorithm;
}
class Program
{
static decimal calculateStandardBonus(decimal sales)
{
return sales / 10;
}
static void Main(string[] args)
{
decimal multiplier = 2;
CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus);
CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
Player[] players = new Player[5];
for (int i = 0; i < 5; i++)
{
players[i] = new Player();
}
players[0].Name = "Sergio";
players[0].Score = 240;
players[0].calculation_algorithm = standard_bonus;
players[1].Name = "Sergio";
players[1].Score = 240;
players[1].calculation_algorithm = enhanced_bonus;
players[2].Name = "Caro";
players[2].Score = 89;
players[2].calculation_algorithm = standard_bonus;
players[3].Name = "Andy";
players[3].Score = 38;
players[3].calculation_algorithm = enhanced_bonus;
players[4].Name = "Hugo";
players[4].Score = 600;
players[4].calculation_algorithm = enhanced_bonus;
foreach (Player player in players)
{
PerformCalculationBonus(player);
}
foreach (Player player in players)
{
DisplayPersonalDetails(player);
}
Console.ReadLine();
}
public static void PerformCalculationBonus(Player player)
{
player.Bonus = player.calculation_algorithm(player.Score);
}
public static void DisplayPersonalDetails(Player player)
{
Console.WriteLine(player.Name);
Console.WriteLine(player.Score);
Console.WriteLine(player.Bonus);
Console.WriteLine("---------------");
}
}
}
Anonymous delegates are designed to help you make code more readable by being able to define the behavior of a simple delegate inline in another method. This means that if you're dealing with something that requires a delegate (an event handler, for example), you can define the behavior right in the code rather than creating a dedicated function for it.
In addition, they're the precursor for lambda expressions. Things like LINQ to Objects (any of the methods that operate on IEnumerable<T>) use delegates to perform queries on objects. For example, if you have a collection of strings and you want a query that finds all of them that are five characters long, you can do that with a lambda:
List<string> strings = ...
var query = strings.Where(s => s.Length == 5);
Or you could do it with an anonymous delegate:
var query = strings.Where(delegate(string s) { return s.Length == 5; });
If you didn't have these, your code would look something like this:
var query = strings.Where(IsFiveCharacters);
...
private bool IsFiveCharacters(string input)
{
return input.Length == 5;
}
It's important to realize, though, that lambdas and anonymous delegates are just compiler features. When your code is compiled, it does actually create regular functions like in the last example, but they're hidden and named using characters that are illegal in the language being used. There's a lot of logic that goes around them when doing things like closures (where you access a variable that exists outside of the lambda/anonymous delegate declaration), as well.
The benefit is that you don't have to look somewhere else for the code to do a one-time lookup/change/calculation/whatever. It's a bit annoying to have to add a function (or a whole other class for a function!) you'll only ever use in one place, and then you have to look back later and see what that bit of code was and why it's needed and whether it still is.
With an anonymous delegate, the code is right there in the code that uses it.

Cannot use ref or out parameter in lambda expressions

Why can't you use a ref or out parameter in a lambda expression?
I came across the error today and found a workaround but I was still curious why this is a compile-time error.
CS1628: Cannot use in ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression
Here's a simple example:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
Lambdas have the appearance of changing the lifetime of variables that they capture. For instance, the following lambda expression causes the parameter p1 to live longer than the current method frame as its value can be accessed after the method frame is no longer on the stack
Func<int> Example(int p1) {
return () => p1;
}
Another property of captured variables is that changes to the variables are also visible outside the lambda expression. For example, the following code prints out 42
void Example2(int p1) {
Action del = () => { p1 = 42; };
del();
Console.WriteLine(p1);
}
These two properties produce a certain set of effects which fly in the face of a ref parameter in the following ways:
ref parameters may have a fixed lifetime. Consider passing a local variable as a ref parameter to a function.
Side effects in the lambda would need to be visible on the ref parameter itself. Both within the method and in the caller.
These are somewhat incompatible properties and are one of the reasons they are disallowed in lambda expressions.
Under the hood, the anonymous method is implemented by hoisting captured variables (which is what your question body is all about) and storing them as fields of a compiler generated class. There is no way to store a ref or out parameter as a field. Eric Lippert discussed it in a blog entry. Note that there is a difference between captured variables and lambda parameters. You can have "formal parameters" like the following as they are not captured variables:
delegate void TestDelegate (out int x);
static void Main(string[] args)
{
TestDelegate testDel = (out int x) => { x = 10; };
int p;
testDel(out p);
Console.WriteLine(p);
}
You can but you must explicitly define all the types so
(a, b, c, ref d) => {...}
Is invalid, however
(int a, int b, int c, ref int d) => {...}
Is valid
As this is one of the top results for "C# lambda ref" on Google; I feel I need to expand on the above answers. The older (C# 2.0) anonymous delegate syntax works and it does support more complex signatures (as well closures). Lambda's and anonymous delegates at the very least have shared perceived implementation in the compiler backend (if they are not identical) - and most importantly, they support closures.
What I was trying to do when I did the search, to demonstrate the syntax:
public static ScanOperation<TToken> CreateScanOperation(
PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
return delegate(string text, ref int position, ref PositionInformation currentPosition)
{
var token = oldScanOperation(text, ref position, ref currentPosition);
if (token == null)
return null;
if (tokenDefinition.LeftDenotation != null)
token._led = tokenDefinition.LeftDenotation(token);
if (tokenDefinition.NullDenotation != null)
token._nud = tokenDefinition.NullDenotation(token);
token.Identifier = tokenDefinition.Identifier;
token.LeftBindingPower = tokenDefinition.LeftBindingPower;
token.OnInitialize();
return token;
};
}
Just keep in mind that Lambdas are procedurally and mathematically safer (because of the ref value promotion mentioned earlier): you might open a can of worms. Think carefully when using this syntax.
And maybe this?
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
var val = value;
int newValue = array.Where(a => a == val).First();
}
You can not use an out parameter directly in a lambda expression. The reason why you can not do that is explained in the other answers.
Workaround
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
private static int OuterFunc (int i_param1, out int o_param2)
{
int param2 = 0;
var del = () => InnerFunc (i_param1, out param2);
int result = del ();
o_param2 = param2;
return result;
}
private static int InnerFunc (int i_param1, out int o_param2)
{
o_param2 = i_param1;
return i_param1;
}
private static void Main (string[] args)
{
int result = OuterFunc (123, out int param2);
Console.WriteLine (result); // prints '123'
Console.WriteLine (param2); // prints '123'
}
Please note
The question was created in 2009. My answer was created in 2023 using C#10 and .NET 6. I don't know whether this answer had also worked back in 2009, which means, the code here might depend on enhancements to C# and .NET that might have been made in the meantime.
I will give you another example.
Description
The code below will throw out this error. Because the change brought by the lambda expression (i)=>{...} only works in the function test.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
Solution
So, if you remove out of the parameter, it works.
static void test(System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
If you need out really, don't change the parameter in the lambda expression directly. Instead, use a temporary variable please.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
System.Drawing.Image[] bitmapsTemp = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmapsTemp[i] = System.Drawing.Image.FromFile("2.bmp");
});
bitmaps = bitmapsTemp;
}

Refactoring with Lambda's and Delegates

I've just installed VS2008 and have run into a problem that I'm sure can be solved with either lambda's or delegates (or a combination!).
private string ReadData(TcpClient s, string terminator)
{
// Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
var sb = new StringBuilder();
do
{
var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
} while (s.GetStream().DataAvailable && !sb.ToString().Contains(terminator));
return sb.ToString();
}
The problem is, sometimes I need to check if the string contains either of two different values. Sometimes I may need to check it for three values.
So what I propose, is to change " !sb.ToString().Contains(terminator)" to a function that is passed into the method.
I could write my different functions such as:
private bool compare1(string s, string t) {
return s.contains(t)
}
private bool compare2(string s, string t1, string t2) {
return (s.compare(t1) or s.compare(t2)
}
// etc...
Then when I want to compare with 3 different values, create a delegate to one of these functions, then pass that to the ReadData() method.
I'm very clueless when it comes to delegates, and I'm not sure if this seems like the right place for a lambda but something is telling me it is.
The calling code is this:
// Enter username .
if (HasData(s,"login:"))
SendData(s, switchUser + TelnetHelper.CRLF);
HasData is identical to ReadData, but returns a bool instead of a string (which I'd also like to factor out into one method using some trickery - but that's a secondary question - feel free to answer that though.
Just for reference:
private bool HasData(TcpClient s, string terminator)
{
// Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
var sb = new StringBuilder();
do
{
var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
} while (s.GetStream().DataAvailable && !sb.ToString().Contains(terminator));
return sb.ToString().Contains(terminator);
}
It sounds like you're looking for a predicate function. Instead of hard coding the check, take a delegate as a parameter than can do the check
private string ReadData(TcpClient s, Func<string,bool> predicate)
{
// Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
var sb = new StringBuilder();
do
{
var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
} while (s.GetStream().DataAvailable && !predicate(sb));
return sb.ToString();
}
Then you can create several wrappers which just create the appropriate delegate and pass it down
public bool HasData(TcpClient c, string terminator) {
return HasData(c, (s) => s.Contains(terminator));
}
public bool HasData(TcpClient c, string t1, string t2) {
return HasData(c, (s) => s.Contains(t1) || s.Contains(t2));
}
You can even build a delegate on the fly based on arbitrary number of terminators
public bool HasData(TcpClient c, params string[] terminatorList) {
return HasData(c, (s) => terminatorList.Where(x => s.Contains(x)).Any());
}
One option would be to overload the ReadData() method to take a string array containing the values that you are checking for. Using an extension method, you could extend Contains() to take a string array.
Your ReadData() method could be:
private string ReadData(TcpClient s, string[] terminators) {
// Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
var sb = new StringBuilder();
do
{
var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
} while (s.GetStream().DataAvailable && !sb.ToString().Contains(terminators));
return sb.ToString();
}
The Contains() method extension could be:
public static bool Contains ( this String str , String[] testValues )
{
foreach ( var value in testValues )
{
if ( str.Contains( value ) )
return true;
}
return false;
}
This implementation eliminates the need to create a new predicate each time you have a different number of strings to test for.
Because the syntax of the lambdas is somewhat foreign to myself (and the rest of my team) I ended up going with a slightly different solution. I couldn't figure out the syntax of .All() when modified from the .Any() function above.
I needed an .All() function as well, to ensure all the terminators in the list were found. So I ended up going with something like the following:
delegate bool Predicate (string s, params [] string terminators);
bool HasAll(string s, params string [] terminators) {
foreach (var t in terminators) {
if (!s.contains(t)) return false;
}
return true;
}
bool HasAny(string s, params string [] terminators) {
foreach (var t in terminators) {
if (s.contains(t)) return true;
}
return false;
}
// Just looking now, I could also pass in a bool to switch between the two and remove one of these functions. But this is fairly clear
string ReadData(TcpClient sock, Function predicate, params [] string terminators) {
var sb = new StringBuilder();
do
{
var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
} while (s.GetStream().DataAvailable && !predicate(sb.ToString(), terminators);
return sb.ToString();
}
Then the calling code looks like:
private void someFunc()
{
Predicate any = new Predicate(HasAny);
Predicate all = new Predicate(HasAll);
String response;
// Check all strings exist
response = ReadData(this.sock, all, "(", ")", "->")
if (all(response, "(", ")", "->")
SendData(this.sock, ...);
// Check any string exists
response = ReadData(this.sock, any, "Hi", "Hey", "Hello");
if (any(response, "Hi", "Hey", "Hello"))
SendData(this.sock, ...);
}
I'll probably add null checks into the Has[Any|All] functions, reverse the do..while to a while, and just check response != null instead of duplicating the params. This solutions suits all my use cases and is fairly human readable I think. As long as I make the small changes I mentioned just above.
This whole thing highlights for me my need to learn lambda expressions though!

Categories

Resources