让我们说这里有一个过于简单的代码:
class Person
{
public int age;
public string name;
public Person(int age, string name)
{
this.age = age;
this.name = name;
}
}
public class MySimpleDatabase
{
List<Person> people;
internal List<Person> People
{
get
{
if(people == null)
{
people = new List<Person>();
people.Add(new Person(24, "ASD"));
people.Add(new Person(35, "QWE"));
people.Add(new Person(12, "MNB"));
}
return people;
}
}
}
public class ProcessPeopleConcrete
{
public void WriteNames()
{
List<Person> people = new MySimpleDatabase().People;
foreach (var person in people)
{
Console.WriteLine(person.name);
}
}
}
public class ProcessPeopleInterface
{
public void WriteNames()
{
//question for here.
IEnumerable<Person> people = new MySimpleDatabase().People;
foreach (var person in people)
{
Console.WriteLine(person.name);
}
}
}
这里我有具体的处理器以及基于接口的处理器。这里接口处理器当然更易于维护,但据我所知
//edited here to clarify
我只能为我需要的变量指定一个类型,在我的情况下,它是IEnumerable<Person>
。
如果我需要那些同时实现不是一个但两个接口 的东西,那么每个都与其他(一个没有实现另一个)?
所以说我需要任何必须实施 ICloneable
和IEnumerator
的集合。在评论中,正确地说我可以定义另一个实现它们的接口。但是,如果我使用预定义的集合,我不能这样做,因为我们将无法抛出任何它们,因为它们显然没有实现我的自定义接口。
在这种情况下,我将为变量people
指定哪种类型(在此处注明“问题”)?如果有一个像<IEnumerable, ICloneable> people;
这样的变量声明会假设我需要一些实现 IEnumerable
和ICloneable
的东西。但是有没有类似的语言特征,或者它就是我所说的 - 只是虚构的?
答案 0 :(得分:1)
正如您所知,您不能强制类实现它们不能实现的接口;)
您还注意到接口用于解决特定问题。在一种情况下,他们解决了如何枚举集合,而在另一种情况下,他们解决了如何克隆对象。
从你的问题我认为你希望能够告诉返回的对象解决了这两个问题,你想知道如何在方法合同中告诉它。
您可以通过定义新界面来实现:
public interface ISuperClonableList<T> : IEnumerable<T>, IClonable
{
}
就是这样。
如果列表本身不可克隆,则需要将其包装在实现两个接口的新类中。将实际列表作为构造函数参数传递,并在每个IEnumerable方法实现中调用它。
克隆接口的问题在于它们通常不指定它应该是深度还是浅度克隆。重要的是要知道,如果包含的项目是可变的,它可能会导致很大的问题。
从ReSharper生成的示例:
public class MyListWrapper<T> : ISuperClonableList<T>
{
private readonly ISuperClonableList<T> _innerList;
public MyListWrapper(ISuperClonableList<T> innerList)
{
_innerList = innerList;
}
public IEnumerator<T> GetEnumerator()
{
return _innerList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) _innerList).GetEnumerator();
}
public void Add(T item)
{
_innerList.Add(item);
}
public void Clear()
{
_innerList.Clear();
}
public bool Contains(T item)
{
return _innerList.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_innerList.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return _innerList.Remove(item);
}
public int Count
{
get { return _innerList.Count; }
}
public bool IsReadOnly
{
get { return _innerList.IsReadOnly; }
}
public int IndexOf(T item)
{
return _innerList.IndexOf(item);
}
public void Insert(int index, T item)
{
_innerList.Insert(index, item);
}
public void RemoveAt(int index)
{
_innerList.RemoveAt(index);
}
public T this[int index]
{
get { return _innerList[index]; }
set { _innerList[index] = value; }
}
}
答案 1 :(得分:1)
这可能不是你想要的,但这里有类似于你的概念。我创建了一个接受IEnumerable和IList的Tuple的简单函数,然后你可以向它提供参数:
public static void Foo(Tuple<IEnumerable<int>, IList<int>> complex)
{
foreach (var item in complex.Item1)
{
Console.WriteLine(item.ToString());
}
complex.Item2.Add(9);
}
一个简单的清单:
List<int> ints = new List<int>
{
1,
3,
5,
7
};
然后通过首先实例化一个单独的变量来调用该函数,就像我一样,或者将实例化直接写入Foo()函数。
Tuple<IEnumerable<int>, IList<int>> tuple = Tuple.Create((ints as IEnumerable<int>), (ints as IList<int>));
Foo(tuple);
我也对真正的解决方案感兴趣,只要 一个。