EnumerableDefaults.first(Enumerable) now closes the enumerator.
diff --git a/src/main/java/net/hydromatic/linq4j/EnumerableDefaults.java b/src/main/java/net/hydromatic/linq4j/EnumerableDefaults.java
index 3df8d8b..29afdfd 100644
--- a/src/main/java/net/hydromatic/linq4j/EnumerableDefaults.java
+++ b/src/main/java/net/hydromatic/linq4j/EnumerableDefaults.java
@@ -476,7 +476,15 @@
* by Enumerable.)
*/
public static <TSource> TSource first(Enumerable<TSource> enumerable) {
- return enumerable.iterator().next();
+ final Enumerator<TSource> os = enumerable.enumerator();
+ try {
+ if (os.moveNext()) {
+ return os.current();
+ }
+ throw new NoSuchElementException();
+ } finally {
+ os.close();
+ }
}
/**
diff --git a/src/test/java/net/hydromatic/linq4j/test/Linq4jTest.java b/src/test/java/net/hydromatic/linq4j/test/Linq4jTest.java
index 5a2aa84..7192ea9 100644
--- a/src/test/java/net/hydromatic/linq4j/test/Linq4jTest.java
+++ b/src/test/java/net/hydromatic/linq4j/test/Linq4jTest.java
@@ -403,6 +403,54 @@
Department d = depts[0];
assertEquals(d, depts[0]);
assertEquals(d, Linq4j.asEnumerable(depts).first());
+
+ try {
+ String s = Linq4j.<String>emptyEnumerable().first();
+ fail("expected exception, got " + s);
+ } catch (NoSuchElementException ex) {
+ // ok
+ }
+
+ // close occurs if first throws
+ final int[] closeCount = {0};
+ try {
+ String s = myEnumerable(closeCount, 0).first();
+ fail("expected exception, got " + s);
+ } catch (NoSuchElementException ex) {
+ // ok
+ }
+ assertThat(closeCount[0], equalTo(1));
+
+ // close occurs if first does not throw
+ closeCount[0] = 0;
+ final String s = myEnumerable(closeCount, 1).first();
+ assertThat(s, equalTo("x"));
+ assertThat(closeCount[0], equalTo(1));
+ }
+
+ private Enumerable<String> myEnumerable(final int[] closes, final int size) {
+ return new AbstractEnumerable<String>() {
+ public Enumerator<String> enumerator() {
+ return new Enumerator<String>() {
+ int i = 0;
+
+ public String current() {
+ return "x";
+ }
+
+ public boolean moveNext() {
+ return i++ < size;
+ }
+
+ public void reset() {
+ }
+
+ public void close() {
+ ++closes[0];
+ }
+ };
+ }
+ };
}
@Test public void testFirstPredicate1() {