Affects: PDFSharp v1.31.1789.0, both GDI+ build and WPF build;
Attempting to iterate a PdfAnnotations instance with a foreach loop results in an InvalidCastException:
Code:
foreach (var annotation in page.Annotations)
{
...
}
Quote:
Unable to cast object of type 'AnnotationsIterator' to type 'System.Collections.Generic.IEnumerator`1[PdfSharp.Pdf.PdfItem]'
at PdfSharp.Pdf.Annotations.PdfAnnotations.GetEnumerator()
In v1.2, the PdfArray class implemented IEnumerable, and the nested AnnotationsIterator class implemented IEnumerator; everything worked as expected.
Code:
public sealed class PdfAnnotations : PdfArray
{
...
public override IEnumerator GetEnumerator()
{
return new AnnotationsIterator(this);
}
class AnnotationsIterator : IEnumerator { ... }
}
In v1.31, PdfArray implements IEnumerable<PdfItem>, and AnnotationsIterator implements IEnumerator<PdfAnnotation>. The PdfAnnotations.GetEnumerator method creates a new instance of the AnnotationsIterator, and attempts to cast it to IEnumerator<PdfItem>. This would work in .NET 4.0, but fails in 2.0, 3.0 or 3.5, as generic covariance is not available.
Code:
public sealed class PdfAnnotations : PdfArray
{
...
public override IEnumerator<PdfItem> GetEnumerator()
{
return (IEnumerator<PdfItem>)new AnnotationsIterator(this);
}
class AnnotationsIterator : IEnumerator<PdfAnnotation> { ... }
}
To fix this, the AnnotationsIterator class needs to implement IEnumerator<PdfItem> instead of IEnumerator<PdfAnnotation>. The PdfAnnotations.GetEnumerator method will then work without the cast.
Code:
public sealed class PdfAnnotations : PdfArray
{
...
public override IEnumerator<PdfItem> GetEnumerator()
{
return new AnnotationsIterator(this);
}
class AnnotationsIterator : IEnumerator<PdfItem> { ... }
}
The only workaround for v1.31 is to iterate manually:
Code:
for (int index = 0; index < page.Annotations.Count; index++)
{
var annotation = page.Annotations[index];
...
}