Возможно, этот вопрос уже задавался миллион раз, но я не мог найти подобную тему. Можно ли написать общий класс с несколькими «где», которые будут проверяться во время компиляции? Вот что я сегодняВозможно ли иметь C++-подобных дженериков в C#?
public class MsBitsEnumWrapper<TC, TE> : IEnumerable<TC>
{
internal class Helper : IEnumerator<TC>
{
private readonly TC[] _data;
private int _pos = -1;
private readonly IEnumBackgroundCopyJobs _jobs;
private readonly IEnumBackgroundCopyFiles _files;
// I miss C++ templates that allows me to implements this method in completelly generic fashion...
public Helper(TE source)
{
_jobs = source as IEnumBackgroundCopyJobs;
_files = source as IEnumBackgroundCopyFiles;
uint count = 0;
if (null != _jobs)
{
_jobs.GetCount(out count);
_jobs.Reset();
}
else
if (null != _files)
{
_files.GetCount(out count);
_files.Reset();
}
_data = new TC[count];
for (uint i = 0; i < count; ++i)
{
uint fetched = 0;
if (null != _jobs)
{
IBackgroundCopyJob job;
_jobs.Next(1, out job, ref fetched);
_data[i] = (TC)job;
}
else
if (null != _files)
{
IBackgroundCopyFile file;
_files.Next(1, out file, ref fetched);
_data[i] = (TC)file;
}
}
}
#region Implementation of IDisposable
public void Dispose() { }
#endregion
#region Implementation of IEnumerator
public bool MoveNext()
{
if (_pos < (_data.Length - 1))
{
_pos++;
return true;
}
return false;
}
public void Reset()
{
_pos = -1;
}
public TC Current
{
get { return _data[_pos]; }
}
object IEnumerator.Current
{
get { return Current; }
}
#endregion
}
private readonly Helper _enumerator;
public MsBitsEnumWrapper(TE source) { _enumerator = new Helper(source); }
#region Implementation of IEnumerable
public IEnumerator<TC> GetEnumerator() { return _enumerator; }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
#endregion
}
Очевидно, что я не люблю его, потому что я должен иметь переключатель в время выполнения, которые определяют тип родового аргумента. Возможно ли иметь что-то подобное?
public class MsBitsEnumWrapper<TC, TE> : IEnumerable<TC>
where TE : IEnumBackgroundCopyJobs, IEnumBackgroundCopyFiles
where TC : IBackgroundCopyJob, IBackgroundCopyFile
{
internal class Helper : IEnumerator<TC>
{
private readonly TC[] _data;
private int _pos = -1;
private readonly TE _iface;
// I miss C++ templates that allows me to implements this method in completelly generic fashion...
public Helper(TE source)
{
_iface = source;
uint count;
_iface.GetCount(out count);
_iface.Reset();
_data = new TC[count];
for (uint i = 0; i < count; ++i)
{
uint fetched = 0;
TC job;
_iface.Next(1, out job, ref fetched);
_data[i] = job;
}
}
#region Implementation of IDisposable
public void Dispose() { }
#endregion
#region Implementation of IEnumerator
public bool MoveNext()
{
if (_pos < (_data.Length - 1))
{
_pos++;
return true;
}
return false;
}
public void Reset()
{
_pos = -1;
}
public TC Current
{
get { return _data[_pos]; }
}
object IEnumerator.Current
{
get { return Current; }
}
#endregion
}
private readonly Helper _enumerator;
public MsBitsEnumWrapper(TE source) { _enumerator = new Helper(source); }
#region Implementation of IEnumerable
public IEnumerator<TC> GetEnumerator() { return _enumerator; }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
#endregion
}
Я понимаю, что это не будет работать, если общий определяется с TE = IEnumBackgroundCopyJobs и TC = IBackgroundCopyFile, но так как я тот, кто определяет TE и TC и прототипы функций из заданных интерфейсов равно было бы хорошо, если бы он работал таким образом.
Может быть, есть еще один способ упростить текущий код?
Спасибо!
Чего вы пытаетесь достичь? Каким конкретным способом код, который вы разместили, не делает то, что вам нужно? Отправьте * небольшой * образец кода, который не работает, и укажите ошибку, которую вы получите. – Timwi
Целью является возможность перечисления через экземпляр COM-интерфейсов IEnumBackgroundCopyFiles или IEnumBackgroundCopyJobs с использованием «foreach». Первая реализация - это то, что используется сегодня в производстве. Пример использования: IEnumBackgroundCopyFiles temp; job.EnumFiles (out temp); var files = new MsBitsEnumWrapper (temp); foreach (файл IBackgroundCopyFile в файлах) {} ::: Здесь мне нужно проверить время выполнения (в конструкторе), если данный параметр является экземпляром того или иного типа путем кастинга через «как». Я хотел бы иметь более общее решение. –
expert
ruslan, вы включаете слишком много неуместных деталей. Кроме того, пожалуйста, не пытайтесь вставить информацию в комментарий. Пожалуйста, отредактируйте вопрос, удалите все ненужные детали и код и задайте * сам вопрос * только с информацией, которая является * релевантной *, но, конечно, включая * все * соответствующую информацию. – Timwi