Реализация интерфейса - C# (179705)
Формулировка задачи:
Написал пример из книги O'Reilly Learning C# 3.0 Chapter 18 создание File-Copier. Все сделал "по инструкции" и несколько раз перепроверил код, но работает с ошибками (их очень много), но хотел бы разобраться хотя бы по основным вопросам, указанных в комментариях (или подскажите где можно почитать):
1. fileList.Sort(comparer);//Почему мы здесь передаем ссылку на объект, в котором реализована только одна ф-ия
Compaprer, а не на саму функцию - comparer.Comparer(file1, file2)? Она же не должна вызываться сама по себе.. Как это возможно? (153 строка)
2. public int Comparer(FileInfo file1, FileInfo file2)// почему компилятор не видит здесь реализацию интерфейса?
//пробовал изменить название на IComparer<FileInfo>.Comparer, но безуспешно... Почему? (173)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace File_Copier
{
public partial class FrmFileCopier : Form
{
private const int MaxLevel = 2;
public FrmFileCopier()
{
InitializeComponent();
FillDirectoryTree(tvwSource, true);
FillDirectoryTree(tvwTargetDir, false);
}
private void FillDirectoryTree(TreeView tvw, bool isSource)
{
tvw.Nodes.Clear();
string[] strDrives = Environment.GetLogicalDrives();
foreach(string rootDirectoryName in strDrives)
{
try
{
DirectoryInfo dir = new DirectoryInfo(rootDirectoryName);
dir.GetDirectories();
TreeNode ndRoot = new TreeNode(rootDirectoryName);//create ndRoot to hold the directories
tvw.Nodes.Add(ndRoot);
if (isSource) { GetSubDirectoryNodes(ndRoot, ndRoot.Text, true, 1); }
else { GetSubDirectoryNodes(ndRoot, ndRoot.Text, false, 1); }
}
catch { }
Application.DoEvents();
}
}
private void GetSubDirectoryNodes(TreeNode parentNode, string fullName, bool getFileNames, int level)
{
DirectoryInfo dir = new DirectoryInfo(fullName);
DirectoryInfo[] dirSubs = dir.GetDirectories();
foreach(DirectoryInfo dirSub in dirSubs)
{
if ((dirSub.Attributes & FileAttributes.Hidden) != 0) { continue; }
TreeNode subNode = new TreeNode(dirSub.Name);
parentNode.Nodes.Add(subNode);
if (level < MaxLevel)
{
GetSubDirectoryNodes(subNode, dirSub.FullName, getFileNames, level + 1);
}
if (getFileNames)
{
FileInfo[] files = dir.GetFiles();
foreach(FileInfo file in files)
{
TreeNode fileNode = new TreeNode(file.Name);
parentNode.Nodes.Add(fileNode);
}
}
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private void tvwSource_AfterCheck(object sender, TreeViewEventArgs e)
{
SetCheck(e.Node, e.Node.Checked);
}
private void SetCheck(TreeNode node, bool check)
{
foreach(TreeNode n in node.Nodes)
{
n.Checked = check; //check the node
if (n.Nodes.Count != 0) { SetCheck(n, check); }
}
}
private void tvwSource_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
tvwExpand(sender, e.Node);
}
private void tvwExpand(object sender, TreeNode currentNode)
{
TreeView tvw = (TreeView)sender;
bool getFiles = (tvw == tvwSource);
string fullName = currentNode.FullPath;
currentNode.Nodes.Clear();
GetSubDirectoryNodes(currentNode, fullName, getFiles, 1);
}
private void tvwTargetDir_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
tvwExpand(sender, e.Node);
}
private void tvwTargetDir_AfterSelect(object sender, TreeViewEventArgs e)
{
string theFullPath = e.Node.FullPath;
if (theFullPath.EndsWith(""))
{
theFullPath = theFullPath.Substring(0, theFullPath.Length - 1);
}
txtTargetDir.Text = theFullPath;
}
private void btnClear_Click(object sender, EventArgs e)
{
foreach(TreeNode node in tvwSource.Nodes) { SetCheck(node, false); }
}
private void btnCopy_Click(object sender, EventArgs e)
{
List<FileInfo> fileList = GetFileList();
foreach(FileInfo file in fileList)
{
try
{
lblStatus.Text = "Copying " + txtTargetDir.Text + "" + file.Name + "...";
Application.DoEvents();
file.CopyTo(txtTargetDir.Text + "" + file.Name, chkOverwrite.Checked);
}
catch(Exception ex) { MessageBox.Show(ex.Message); }
}
lblStatus.Text = "Done.";
//Application.DoEvents();
}
private List<FileInfo> GetFileList()
{
List<string> fileNames = new List<string>();
foreach(TreeNode theNode in tvwSource.Nodes)
{
GetCheckedFiles(theNode, fileNames);
}
List<FileInfo> fileList = new List<FileInfo>();
foreach(string fileName in fileNames)
{
FileInfo file = new FileInfo(fileName);
if (file.Exists) { fileList.Add(file); }
}
IComparer<FileInfo> comparer = (IComparer<FileInfo>) new FileComparer();// создаем интерфейсную ссылку на объект класса
fileList.Sort(comparer);//Почему мы здесь передаем ссылку на объект, в котором реализована только одна ф-ия
//Compaprer, а не на саму функцию? Она же не вызывается сама по себе...
return fileList;
}
private void GetCheckedFiles(TreeNode node, List<string> fileNames)
{
if(node.Nodes.Count==0)//if this is a leaf...
{
if(node.Checked)//if the node was checked...
{
fileNames.Add(node.FullPath);//if the node was checked...
}
}
else
{
foreach(TreeNode n in node.Nodes) { GetCheckedFiles(n, fileNames); }
}
}
public class FileComparer: IComparer<FileInfo>
{
public int Comparer(FileInfo file1, FileInfo file2)// почему компилятор не видит здесь реализацию интерфейса?
//пробовал изменить название на IComparer<FileInfo>.Comparer, но безуспешно... Почему?
{
if (file1.Length > file2.Length) { return -1; }
if (file1.Length < file2.Length) { return 1; }
return 0;
}
int IComparer<FileInfo>.Compare(FileInfo x, FileInfo y)// этой функции в примере нет, но без нее не работает -
// не реализован интерфейс
{
throw new NotImplementedException();
}
}
private void btnDelete_Click(object sender, EventArgs e)
{
System.Windows.Forms.DialogResult result =
MessageBox.Show(
"Are you quite sure?",
"Delete Files",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button2);
if(result== System.Windows.Forms.DialogResult.OK)
{
List<FileInfo> fileNames = GetFileList();
foreach (FileInfo file in fileNames)
{
try
{
lblStatus.Text = "Deleting " + txtTargetDir.Text + "" + file.Name + "...";
Application.DoEvents();
file.Delete();
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
lblStatus.Text = "Done.";
Application.DoEvents();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}Решение задачи: «Реализация интерфейса»
textual
Листинг программы
void Sort(IComparer comparer)
{
...
int result = comparer.Compare(arr[i], arr[j]);
...
}