Proprio come molte persone credono tenacemente in piccole funzioni , alcune persone credono che lambda debba contenere solo frammenti di codice ridotto.
Un vantaggio spesso trascurato di lambda tuttavia, se li stai utilizzando puoi incapsulare un comportamento che altrimenti dovresti rendere disponibile all'intera classe .
Non è un vero vantaggio mantenere l'incapsulamento corretto, indipendentemente dal conteggio delle righe? Quali sono i possibili svantaggi dell'uso di funzioni anonime con molte righe di codice che sto trascurando?
Quello che segue è un esempio reale. argumentsMatch
esegue una corrispondenza argomento molto specifica, strongmente dipendente dal comportamento della funzione in cui è definita. Il seguente codice IMHO segue il principio di singola responsabilità . Lo spostamento di argumentsMatch
in un metodo privato comporterebbe che venisse richiamato solo da questo metodo.
/// <summary>
/// Get the first found matching generic type.
/// The type parameters of the generic type are optional.
/// E.g. Dictionary<,>
/// When full (generic) type is known (e.g. Dictionary<string,string>),
/// the "is" operator is most likely more performant,
/// but this function will still work correctly.
/// </summary>
/// <param name = "source">The source for this extension method.</param>
/// <param name = "type">The type to check for.</param>
/// <returns>
/// The first found matching complete generic type,
/// or null when no matching type found.
/// </returns>
public static Type GetMatchingGenericType( this Type source, Type type )
{
Type[] genericArguments = type.GetGenericArguments();
Type rawType = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
// Used to compare type arguments and see whether they match.
Func<Type[], bool> argumentsMatch
= arguments => genericArguments
.Zip( arguments, Tuple.Create )
.All( t => t.Item1.IsGenericParameter || // No type specified.
t.Item1 == t.Item2 );
Type matchingType = null;
if ( type.IsInterface )
{
// Traverse across all interfaces to find a matching interface.
matchingType =
(from t in source.GetInterfaces()
let rawInterface = t.IsGenericType ? t.GetGenericTypeDefinition() : t
where rawInterface == rawType &&
argumentsMatch( t.GetGenericArguments() )
select t).FirstOrDefault();
}
else
{
// Traverse across the type, and all it's base types.
Type baseType = source;
while ( baseType != null && baseType != typeof( object ) )
{
Type rawCurrent = baseType.IsGenericType
? baseType.GetGenericTypeDefinition()
: baseType;
if ( rawType == rawCurrent )
{
// Same raw generic type, compare type arguments.
if ( argumentsMatch( baseType.GetGenericArguments() ) )
{
matchingType = baseType;
break;
}
}
baseType = baseType.BaseType;
}
}
return matchingType;
}