我已经在代码中看到这一行被剪掉了,并且想知道它的使用情况
var item = new List<int>.Enumerator();
这是做什么的?
答案 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
而不是public
或private
的原因......它有点复杂。 internal
实现了List<T>
和IEnumerable<T>
,因此它必须至少有两个带有这些签名的方法:
IEnumerable
和
IEnumerator<T> IEnumerable<T>.GetEnumerator()
但出于性能原因,它将它们实现为显式实现(因此隐藏它们),并实现第三种方法:
IEnumerator IEnumerable.GetEnumerator()
返回public Enumerator GetEnumerator()
...现在,由于struct Enumerator
的工作原理,第三个公共方法将是foreach
使用的方法。为什么这个?因为通过其中一个接口(在这种情况下为foreach
或struct
)使用的IEnumerator<T>
被加框(某些东西会减慢它的速度)......但是如果IEnumerator
是直接使用(通过其struct
)方法,没有拳击,性能更好一点......微软程序员在public Enumerator GetEnumerator()
表现上给出了110%: - )
答案 1 :(得分:1)
因此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;
}