C# IEnumerator/yield structure potentially bad?

前端 未结 11 1314
面向向阳花
面向向阳花 2021-02-01 02:47

Background: I\'ve got a bunch of strings that I\'m getting from a database, and I want to return them. Traditionally, it would be something like this:

public Li         


        
11条回答
  •  时光取名叫无心
    2021-02-01 03:25

    You're not always unsafe with the IEnumerable. If you leave the framework call GetEnumerator (which is what most of the people will do), then you're safe. Basically, you're as safe as the carefullness of the code using your method:

    class Program
    {
        static void Main(string[] args)
        {
            // safe
            var firstOnly = GetList().First();
    
            // safe
            foreach (var item in GetList())
            {
                if(item == "2")
                    break;
            }
    
            // safe
            using (var enumerator = GetList().GetEnumerator())
            {
                for (int i = 0; i < 2; i++)
                {
                    enumerator.MoveNext();
                }
            }
    
            // unsafe
            var enumerator2 = GetList().GetEnumerator();
    
            for (int i = 0; i < 2; i++)
            {
                enumerator2.MoveNext();
            }
        }
    
        static IEnumerable GetList()
        {
            using (new Test())
            {
                yield return "1";
                yield return "2";
                yield return "3";
            }
        }
    
    }
    
    class Test : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("dispose called");
        }
    }
    

    Whether you can affort to leave the database connection open or not depends on your architecture as well. If the caller participates in an transaction (and your connection is auto enlisted), then the connection will be kept open by the framework anyway.

    Another advantage of yield is (when using a server-side cursor), your code doesn't have to read all data (example: 1,000 items) from the database, if your consumer wants to get out of the loop earlier (example: after the 10th item). This can speed up querying data. Especially in an Oracle environment, where server-side cursors are the common way to retrieve data.

提交回复
热议问题