|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
IntroductionInability to pass parameters to predicates often made me consider writing search functions for custom collections. One day I figured enough is enough. In this example I will demonstrate the workaround to passing parameters to predicates, and reasoning involved. There is no download - the code is tiny. I will use MSDN’s example code for List.TrueForAll as the starting point. Intermediate stepWhat if we wanted to reuse the predicate to search not only for dinosaur names that end on “saurus”, but also for those that end on “tor”? Shouldn’t it be easily done?I only kept the minimum required code from MSDN example. To approximate a more common situation, the code is moved into a class DinoClassification, which hypothetically classifies dinosaurs. The predicate and the variable that it uses are made non-static and also moved into that class. using System;
using System.Collections.Generic;
public class DinoClassification
{
private string m_Suffix;
public void Classify()
{
List<string> dinosaurs = new List<string>(new string[] {
"Compsognathus", "Amargasaurus", "Oviraptor", "Velociraptor",
"Deinonychus", "Dilophosaurus", "Gallimimus", "Triceratops"});
m_Suffix = "saurus";
Console.WriteLine("\nFind(EndsWith {0}): {1}", m_Suffix,
dinosaurs.Find(EndsWith));
m_Suffix = "tor";
Console.WriteLine("\nFind(EndsWith {0}): {1}", m_Suffix,
dinosaurs.Find(EndsWith));
}
// Search predicate returns true if a string ends in correct suffix.
private bool EndsWith(String s)
{
if ((s.Length >= m_Suffix.Length) &&
(s.Substring(s.Length - m_Suffix.Length).ToLower() ==
m_Suffix.ToLower()))
{
return true;
}
else
{
return false;
}
}
}
public class Example
{
public static void Main()
{
DinoClassification dcl = new DinoClassification();
dcl.Classify();
}
}
This works in a single-threaded environment. In multi-threaded application we could have
SolutionWhy not do just that? Wrap a variable and a predicate together and tuck away into a separate class.using System;
using System.Collections.Generic;
public class EndsWith
{
private string m_Suffix;
// Initializes with suffix we want to match.
public EndsWith(string Suffix)
{
m_Suffix = Suffix;
}
// Sets a different suffix to match.
public string Suffix
{
get { return m_Suffix; }
set { m_Suffix = value; }
}
// Gets the predicate. Now it's possible to re-use this predicate with
// various suffixes.
public Predicate<string> Match
{
get { return IsMatch; }
}
private bool IsMatch(string s)
{
if ((s.Length >= m_Suffix.Length) &&
(s.Substring(s.Length - m_Suffix.Length).ToLower()
== m_Suffix.ToLower()))
{
return true;
}
else
{
return false;
}
}
}
public class DinoClassification
{
public void Classify()
{
List<string> dinosaurs = new List<string>(new string[] {
"Compsognathus", "Amargasaurus", "Oviraptor", "Velociraptor",
"Deinonychus", "Dilophosaurus", "Gallimimus", "Triceratops"});
Console.WriteLine("\nFind(EndsWith): {0}",
dinosaurs.Find(new EndsWith("saurus").Match));
EndsWith predicate = new EndsWith("tor");
Console.WriteLine("\nFind(EndsWith): {0}",
dinosaurs.Find(predicate.Match));
predicate.Suffix = "hus";
Console.WriteLine("\nFind(EndsWith): {0}",
dinosaurs.Find(predicate.Match));
}
}
public class Example
{
public static void Main()
{
DinoClassification dcl = new DinoClassification();
dcl.Classify();
}
}
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||