class Program
{
private delegate Boolean SomeDelegate(string value);
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
SomeDelegate AA = A;
var test2 = data.DoWhere(AA); //This Line Compile is wrong
}
public static bool A(string value)
{
if (value.StartsWith("d"))
{
return true;
}
return false;
}
}
public static class CustomClass
{
public static IEnumerable<T> DoWhere<T>(this IEnumerable<T> source, Func<T, Boolean> predicate)
{
foreach (T item in source)
{
if (predicate.Invoke(item))
{
yield return item;
}
}
}
}
I want to custom method and condition what data I need. But this code Compile is wrong in var test2 = data.DoWhere(AA);
cannot convert from 'SomeDelegate' to 'System.Func<string, bool>'
And I don't know How to fix it. Please review my code.
SomeDelegate(AA) is not Func<string, bool>. It should simply be a DoWhere(A) in your code. ie:
class Program
{
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var test2 = data.DoWhere(A); //This Line Compile is wrong
}
public static bool A(string value)
{
if (value.StartsWith("d"))
{
return true;
}
return false;
}
}
A simpler way to write it:
class Program
{
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
Func<string, bool> A = value => value.StartsWith("d");
var test2 = data.DoWhere(A);
}
}
Note: Such a function should check if the value is null.
You can't cast an instance of SomeDelegate to a Func<string, bool>:
var test2 = data.DoWhere(AA); //This Line Compile is wrong
Try this instead:
var test2 = data.DoWhere(c => AA(c));
Or use Invoke:
var test2 = data.DoWhere(AA.Invoke);
Or use a method with same signature like A:
var test2 = data.DoWhere(A);
you said in a comment
I just want to custom my own condition method
so code can be much easier of the one you wrote:
public class Program
{
public static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var stringsStartingWithD = data.Where (s => StarstWithD(s)).ToList();
var anotherOne = data.Where (s => SomeOtherTest(s)).ToList();
}
public static bool StarstWithD(string str)
{
if (str.StartsWith("d"))
{
return true;
}
return false;
}
public static bool SomeOtherTest(string str)
{
bool result = false;
// apply desired logic and return true/false
//...
return result;
}
}
For a simple test as the one you are using, you can also avoid creating the StartsWithDmethod and simply use something like this:
public class Program
{
public static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var stringsStartingWithD = data.Where (s => s.StartsWith("d")).ToList();
}
Your entire code is just two lines now
Related
I am running into this error.. not sure what I am missing. This is reproducible code.
Sorry for the edit on the question- What if I wish to pass 2 strings to the function?
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string myString = "test";
string testString = "test";
IDictionary<string, Func<string>> identityInformation = new Dictionary<string, Func<string>>
{
{ "text1", () => {return test(myString, testString); } },
{ "text2", () => { return test(myString, testString); } }
};
}
public static string test(string myString, string testString)
{
return myString;
}
}
EDIT
based on comments you can go with option A and call method when adding item into dictionary
string myString = "test";
string testString = "test";
var identityInformation = new Dictionary<string, string>
{
{ "text1", test(myString, testString) },
{ "text2", test(myString, testString) }
};
public static string test(string myString, string testString)
{
return myString;
}
Not sure which is defined interface you need to follow. There are multiple ways to fix it. Because Func it has no parameters and returns string, which test method is not. Therefore:
A- Change dictionary to store results
Dictionary<string, string>
B- change signature of dictionary to Func<string,string> and store delegates. Then myString as parameter will be used later.
IDictionary<string, Func<string,string>> identityInformation = new Dictionary<string, Func<string,string>>
{
{ "text1", test },
{ "text2", test }
};
C- add lambda
IDictionary<string, Func<string>> identityInformation = new Dictionary<string, Func<string>>
{
{ "text1", () => test(myString) },
{ "text2", () => test(myString) }
};
I have a code like this:
using System;
using System.Collections.Generic;
using System.Linq;
public interface IMyString
{
string Id {get;set;}
};
public class MyString : IMyString
{
public string Id {get;set;}
}
public static class Extensions
{
public static IEnumerable<IMyString> WithId(this IEnumerable<IMyString> source, string id)
{
return source.Where(x => x.Id == id);
}
}
public class Program
{
private static List<T> GetMyStrings<T>(string key, List<T> input)
where T: IMyString
{
return input.WithId(key).ToList();
}
public static void Main()
{
var foo = new List<MyString>{ new MyString { Id = "yes"}, new MyString { Id = "no" } };
var result = GetMyStrings("yes", foo);
var result2 = foo.WithId("no");
Console.WriteLine(result2);
}
}
Why does input.WithId(key).ToList() cause a syntax error, while foo.WithId("no") is OK? Is there a way to make the method GetMyStrings work?
Without the context of your code it is a little difficult to help too much, but your type constraints for the two methods are different. You have two options:
Option 1:
public static class Extensions
{
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id) where T: IMyString
{
return source.Where(x => x.Id == id);
}
}
Option 2:
private static List<IMyString> GetMyStrings(string key, List<IMyString> input)
{
return input.WithId(key).ToList();
}
public static void Main()
{
var foo = new List<IMyString>{ new MyString { Id = "yes"}, new MyString { Id = "no" } };
var result = GetMyStrings("yes", foo);
var result2 = foo.WithId("no");
Console.WriteLine(result2);
}
Here is a dotnetfiddle with the second option as a working piece of code:
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id)
where T : IMyString
{
return source.Where(x => x.Id == id);
}
I am new to Lambda's and Delegates. I think my question may not be a good question but i am trying to write a simple Custom Predicate that act just like a Built-In Prediciate.
So i am going to share my Code: Please share with me that where i am going to make a mistake:
Built-In Predicate Code Example:
namespace Built_In_Predicate
{
class Program
{
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Method 1. Predicate and Anonymous function.
Predicate<string> _Predicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.Find(_Predicate);
Console.WriteLine("Result : {0}", result);
}
}
}
Trying to Create a Custom Predicate (Code):
namespace CustomPredicate
{
class Program
{
// Delegate (Takes some string as a Input and return a Boolean.)
public delegate bool CustomPredicate(string someString);
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Instance of CustomPredicate.
CustomPredicate customPredicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.Find(customPredicate); // its error.
}
}
}
Help will be appreciated.
Delegates cannot be implicitly converted to each other even if they have the same signature.
Find expects a System.Predicate<T> so you have to give it a System.Predicate<T>.
You can write your own Find method if you want to use your own CustomPredicate.
There are also ways to use your customPredicate variable in the call to Find:
_ListOfPlayers.Find(new Predicate<string>(customPredicate));
_ListOfPlayers.Find(customPredicate.Invoke);
You cannot call Find with something else as the type Predicate. But if you want your own delegate, you could call FirstOrDefault (System.Linq) and then use it.
private delegate bool CustomPredicate (string t);
static void Main(string[] args)
{
List<string> _ListOfPlayers = new List<string>()
{
"James Anderson",
"Broad",
"foo"
};
// Method 1. Predicate and Anonymous function.
CustomPredicate _Predicate = delegate (string someString) { return someString.Length == 3; };
string result = _ListOfPlayers.FirstOrDefault(x => _Predicate(x));
Console.WriteLine("Result : {0}", result);
Console.ReadLine();
}
I thought I could make use of the new c# 6 operator nameof to build a dictionary of key/values implicitly from a params array.
As an example, consider the following method call:
string myName = "John", myAge = "33", myAddress = "Melbourne";
Test(myName, myAge, myAddress);
I am not sure there will be an implementation of Test that will be able to imply the name of the elements, from the params array.
Is there a way to do this using just nameof, without reflection ?
private static void Test(params string[] values)
{
List<string> keyValueList = new List<string>();
//for(int i = 0; i < values.Length; i++)
foreach(var p in values)
{
//"Key" is always "p", obviously
Console.WriteLine($"Key: {nameof(p)}, Value: {p}");
}
}
No, that is not possible. You don't have any knowledge of the variables names used. Such information is not passed to the callee.
You could achieve what you want like this:
private static void Test(params string[][] values)
{
...
}
public static void Main(string[] args)
{
string myName = "John", myAge = "33", myAddress = "Melbourne";
Test(new string[] { nameof(myName), myName });
}
Or using a dictionary:
private static void Test(Dictionary<string, string> values)
{
...
}
public static void Main(string[] args)
{
string myName = "John", myAge = "33", myAddress = "Melbourne";
Test(new Dictionary<string, string> { { nameof(myName), myName }, { nameof(myAge), myAge} });
}
Or using dynamic:
private static void Test(dynamic values)
{
var dict = ((IDictionary<string, object>)values);
}
public static void Main(string[] args)
{
dynamic values = new ExpandoObject();
values.A = "a";
Test(values);
}
Another possibility would be the use of an Expression, which you pass in to the method. There you could extract the variable name from the expression and execute the expression for its value.
AddOptional<tblObject>(x =>x.Title, objectToSend.SupplementaryData);
private static void AddOptional<TType>(Expression<Func<TType,string>> expr, Dictionary<string, string> dictionary)
{
string propertyName;
string propertyValue;
Expression expression = (Expression)expr;
while (expression.NodeType == ExpressionType.Lambda)
{
expression = ((LambdaExpression)expression).Body;
}
}
In Above code i would like to get actual value of property title, not ony propert name , is it possible ?
private static void Main(string[] args)
{
CompileAndGetValue<tblObject>(x => x.Title, new tblObject() { Title = "test" });
}
private static void CompileAndGetValue<TType>(
Expression<Func<TType, string>> expr,
TType obj)
{
// you can still get name here
Func<TType, string> func = expr.Compile();
string propretyValue = func(obj);
Console.WriteLine(propretyValue);
}
However, you must be aware that this can be quite slow. You should measure how it performs in your case.
If you don't like to pass your object:
private static void Main(string[] args)
{
var yourObject = new tblObject {Title = "test"};
CompileAndGetValue(() => yourObject.Title);
}
private static void CompileAndGetValue(
Expression<Func<string>> expr)
{
// you can still get name here
var func = expr.Compile();
string propretyValue = func();
Console.WriteLine(propretyValue);
}