介面定義契約,但有時契約「太寬」。例如 ICollection<T> 包含 Add/Remove/Clear,若要實作唯讀集合,這些方法會破壞語意。解決方案:顯式介面實作隱藏不想公開的成員,並在該成員中拋出 NotSupportedException。
public interface IFoo { void Foo(); }
public class Implement : IFoo
{
// 顯式實作:只能透過 IFoo 介面呼叫
void IFoo.Foo() { /* 實作 */ }
}
public class Program
{
static void Main()
{
var impl = new Implement();
// impl.Foo(); // 編譯錯誤:顯式實作成員不可直接呼叫
IFoo foo = (IFoo)impl;
foo.Foo(); // OK
}
}
public class ReadOnlyCollection<T> : ICollection<T>
{
private readonly ICollection<T> _inner;
public ReadOnlyCollection(ICollection<T> collection)
{
_inner = collection ?? throw new ArgumentNullException(nameof(collection));
}
// 安全成員:直接委派
public int Count => _inner.Count;
public bool IsReadOnly => true;
public bool Contains(T item) => _inner.Contains(item);
public void CopyTo(T[] array, int index) => _inner.CopyTo(array, index);
public IEnumerator<T> GetEnumerator() => _inner.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
// 破壞唯讀語意的成員:顯式實作 + 拋出例外
void ICollection<T>.Add(T item) => throw new NotSupportedException("集合為唯讀。");
void ICollection<T>.Clear() => throw new NotSupportedException("集合為唯讀。");
bool ICollection<T>.Remove(T item) => throw new NotSupportedException("集合為唯讀。");
}
NotSupportedException。
4. 即使呼叫端強制轉型為介面,執行時仍會失敗,確保語意正確性。