使用枚举器实例化List

时间:2018-05-18 06:39:41

标签: c# list enumerator

我已经在代码中看到这一行被剪掉了,并且想知道它的使用情况

var item = new List<int>.Enumerator();

这是做什么的?

2 个答案:

答案 0 :(得分:2)

这是非常无用和错误的......

第一个问题应该是什么是import UIKit import CoreData class ToDoListViewController: UITableViewController { var itemArray = [Item]() var selectedCategory : Category?{ didSet { loadItems() } } let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext override func viewDidLoad() { super.viewDidLoad() print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)) } // MARK - Table View DataSource Methods override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return itemArray.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath) let item = itemArray[indexPath.row] cell.textLabel?.text = item.title cell.accessoryType = item.done ? .checkmark : .none return cell } // MARK - Table View Delegate Methods override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { itemArray[indexPath.row].done = !itemArray[indexPath.row].done saveItems() tableView.deselectRow(at: indexPath, animated: true) } @IBAction func addButtonPressed(_ sender: UIBarButtonItem) { var textField = UITextField() let alert = UIAlertController(title: "Add New To Do List Item", message: "", preferredStyle: .alert) let action = UIAlertAction(title: "Add Item", style:.default) { (action) in // This will happend when the user clicks the Add Item on our add UIAlert let newItem = Item(context: self.context) newItem.title = textField.text! newItem.done = false newItem.parentCategory = self.selectedCategory self.itemArray.append(newItem) self.saveItems() } alert.addTextField { (alertTextField) in alertTextField.placeholder = "Create New Item" textField = alertTextField } alert.addAction(action) present(alert, animated: true, completion: nil) } //MARK: - Data Manipulation Methods func saveItems(){ do { try context.save() } catch {print("Error saving context \(error)") } self.tableView.reloadData() } func loadItems(with request: NSFetchRequest<Item> = Item.fetchRequest(), with predicate: NSPredicate? = nil){ let categoryPredicate = NSPredicate(format: "parentCategory.name MATCHES %@", selectedCategory!.name!) if let addtionalPredicate = predicate { request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [categoryPredicate,addtionalPredicate]) }else { request.predicate = categoryPredicate } do { itemArray = try context.fetch(request) } catch { print("Error fetching data from request\(error)") tableView.reloadData() } } } // MARK: - Search Bar Methods extension ToDoListViewController : UISearchBarDelegate { func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { let request : NSFetchRequest<Item> = Item.fetchRequest() let predicate = NSPredicate(format: "title CONTAINS[cd] %@", searchBar.text!) request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] loadItems(with: request, with: predicate) } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchBar.text?.count == 0 { loadItems() DispatchQueue.main.async { searchBar.resignFirstResponder() } } } } ...它是List<T>.Enumerator的支持类,它实现了List<T>接口(用于枚举集合的接口,用于例如IEnumerator<T>)。 For performance reasons it is a struct instead of being a class。作为foreach有一个预定义的公共无参数构造函数(您正在使用的那个)。它甚至有一个带有一个参数(struct)的internal构造函数,它设置了一些必要的内部字段(最重要的是对创建它的List<T> list的引用)。此构造函数由List<>使用。

现在,如果你按照自己所做的写作,你将创建一个不完整的&#34; List<>.GetEnumerator()Enumerator将&#34;工作&#34; (返回item.Current)但如果您尝试default(T),则会获得item.MoveNext()。如果您希望NullReferenceException为&#34;空&#34;收集,最好这样做:

IEnumerator

var item = Enumerable.Empty<int>().GetEnumerator(); List<T>.Enumerator而不是publicprivate的原因......它有点复杂。 internal实现了List<T>IEnumerable<T>,因此它必须至少有两个带有这些签名的方法:

IEnumerable

IEnumerator<T> IEnumerable<T>.GetEnumerator()

但出于性能原因,它将它们实现为显式实现(因此隐藏它们),并实现第三种方法:

IEnumerator IEnumerable.GetEnumerator()

返回public Enumerator GetEnumerator() ...现在,由于struct Enumerator的工作原理,第三个公共方法将是foreach使用的方法。为什么这个?因为通过其中一个接口(在这种情况下为foreachstruct)使用的IEnumerator<T>被加框(某些东西会减慢它的速度)......但是如果IEnumerator是直接使用(通过其struct)方法,没有拳击,性能更好一点......微软程序员在public Enumerator GetEnumerator()表现上给出了110%: - )

答案 1 :(得分:1)

我去了代码了解更多信息,这就是我找到的enter image description here

因此var item = new List<int>.Enumerator();会返回Enumerable结构的实例,该结构将映射到您的列表。由于Enumerator是结构,它将使用默认值初始化其成员,在这种情况下,它将基于代码将列表初始化为null。有关详细信息,请参阅code of list.

在这种情况下,不存在列表实例,因此如果您访问任何类似的方法

var item = new List<int>.Enumerator();
item.Currnet or item.MovNext()

主要抛出异常或默认int你必须尝试这样做。

详细信息:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs

 public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
        {
            private List<T> list;
            private int index;
            private int version;
            private T current;

            internal Enumerator(List<T> list) {
                this.list = list;
                index = 0;
                version = list._version;
                current = default(T);
            }

            public void Dispose() {
            }

            public bool MoveNext() {

                List<T> localList = list;

                if (version == localList._version && ((uint)index < (uint)localList._size)) 
                {                                                     
                    current = localList._items[index];                    
                    index++;
                    return true;
                }
                return MoveNextRare();
            }

            private bool MoveNextRare()
            {                
                if (version != list._version) {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                }

                index = list._size + 1;
                current = default(T);
                return false;                
            }