There some good posts about differences in properties for lists and libraries, e.g. this one from Randy Williams.
My code was
string[] ignoreFields = new string[] { "myField" };
foreach (SPField field in properties.ListItem.Fields)
{
if (!ignoreFields.Contains(field.InternalName) &&
properties.AfterProperties[field.InternalName] != null &&
(properties.ListItem[field.Id] == null ||
properties.ListItem[field.Id].ToString() != properties.AfterProperties[field.InternalName].ToString()))
{
// do something
}
}
This worked well for lists but I struggled with Title column in libraries.
I found properties.AfterProperties["Title"] is always null for libraries even when Title was changed.
After intensive googling I found that for libraries properties.ListItem.Title is mapped to properties.AfterProperties["vti_title"].
So, I had to add this
if (properties.List is SPDocumentLibrary && properties.ListItem.Title != properties.AfterProperties["vti_title"])
{
// do something
}