Ugly thing and advantage of anonymos method -C#
I was asked to explain the ugly thing and advantages of anonymous method.
I explained possibly
Ugly thing
anonymous methods turning quickly into spaghetti code.
Advantages
We can produce thread safe code using anonymous method :Example
static List<string> Names = new List<string>(
new string[] {
"Jon Skeet",
"Marc Gravell",
"David",
"Bill Gates"
开发者_如何转开发 });
static List<string> FindNamesStartingWith(string startingText)
{
return Names.FindAll(
delegate(string name)
{
return name.StartsWith(startingText);
});
}
But really i did not know whether it is thread safe or not.I was asked to justify it. Can any one help me to understand (1) advantages of anonymous methods (2) Is the above code thread safe or not?
Well, "thread safe" is a pretty broad term. What sort of multi-threaded use are you thinking of? I'd expect it to be safe without any data corruption or exceptions if nothing's writing to the list...
Now, as for the "ugliness" of anonymous methods... are you using C# 3? If so, start using lambda expressions, which are generally cleaner:
static List<string> FindNamesStartingWith(string startingText)
{
return Names.FindAll(name => name.StartsWith(startingText));
}
Alternatively, using LINQ:
static List<string> FindNamesStartingWith(string startingText)
{
return Names.Where(name => name.StartsWith(startingText)).ToList();
}
Or if you don't necessarily need a list:
static IEnumerable<string> FindNamesStartingWith(string startingText)
{
return Names.Where(name => name.StartsWith(startingText));
}
Or if you prefer a query expression:
static IEnumerable<string> FindNamesStartingWith(string startingText)
{
return from name in names
where name.StartsWith(startingText)
select name;
}
None of these look like spaghetti code to me. However, if you're going to ask whether you should use this or something else, you should really put forward an alternative. Here's a simple one:
static List<string> FindNamesStartingWith(string startingText)
{
List<string> ret = new List<string>();
foreach (string name in Names)
{
if (name.StartsWith(startingText))
{
ret.Add(name);
}
}
return ret;
}
Do you find that clearer? If so, that's fine - but I suspect it's just that you're not really familiar with anonymous functions, LINQ etc. As you can see, there's significantly more code - it would definitely take me longer to check that that does the right thing than any of the earlier samples.
Well, it all depends on what you mean by thread-safe.
If, during the execution of FindAll
, some other thread changes the underlying Names
collection, then you might get odd results.
Is multiple calls to FindAll
on multiple threads safe by themselves, that is, with only them executing? Yes, that's a definite yes.
As for the advantages of anonymous methods, consider the alternative.
You want to:
- Find some item of the collection
- The only way to know which item you want to find is to evaluate some expression for each one
You could do it like this:
List<string> result = new List<string>();
foreach (string name in Names)
if (name.StartsWith(startingText))
result.Add(name);
return result;
or, given the new lambda syntax, you could do it like this:
return Names.FindAll(name => name.StartsWith(startingText));
I know which one I prefer, but they do different things, with the same result (in this case.)
In the first case, you execute all the code yourself, there's no magic.
In the second case, you give to FindAll
a way to figure out which items to put into the result. There is no non-executable way to do that in this case, you need to have FindAll
execute some code, that you specify, for each item.
精彩评论