I had a similar problem with overlapping catchments (polygons). I solved it using the FeatureIndex class and the IndexQuery2 interface. It is quite fast.
Note that the IIndexQuery2.IntersectedFeatures method includes touching polygons (and would include touching polylines in your case), so I used the IRelationalOperator2 on the result to make sure they were actually overlapping and not just touching. You may want to do the same with IRelationalOperator2.Crosses (though I'm not sure exactly what this means in terms of polylines--it might include polylines that touch at a point, but don't actually cross over each other).
private List<int> CheckForInternalOverlaps(IFeatureClass featureClass)
{
List<int> overlappingOids = new List<int>();
IFeatureIndex indexer = new FeatureIndexClass();
try
{
indexer.FeatureClass = featureClass;
indexer.Index(null, ((IGeoDataset)featureClass).Extent);
IIndexQuery2 indexQuery = (IIndexQuery2)indexer;
IFeatureCursor cursor = featureClass.Search(null, false);
try
{
IFeature catchment = cursor.NextFeature();
while (catchment != null)
{
try
{
object queriedIds;
indexQuery.IntersectedFeatures(catchment.Shape, out queriedIds);
int[] idArray = queriedIds as int[];
if (idArray != null && idArray.Length > 1)
{
// Intersected features will include, source feature itself, and adjacent, non-overlapping features
// We need to check for both.
IRelationalOperator2 relationOp = catchment.Shape as IRelationalOperator2;
for (int i = 0; i < idArray.Length; i++)
{
if (idArray[i] == catchment.OID)
continue;
if (relationOp.Overlaps(featureClass.GetFeature(idArray[i]).Shape))
{
overlappingOids.Add(catchment.OID);
break;
}
}
}
}
finally
{
Marshal.ReleaseComObject(catchment);
}
catchment = cursor.NextFeature();
}
}
finally
{
Marshal.ReleaseComObject(cursor);
}
}
finally
{
Marshal.ReleaseComObject(indexer);
}
return overlappingOids;
}