我倾向于支持显式接口实现而非隐式接口实现,因为我认为针对接口而不是针对实现进行编程通常是可取的,而且在处理Web服务时通常是必需的.
也就是说,我想知道为什么以下是非法的显式接口声明和合法的隐式接口:
interface IConnection
{
string ConnectionString { get; }
}
class Connection1 : IConnection
{
// private set is illegal, won't compile
string IConnection.ConnectionString { get; private set; }
}
class Connection2 : IConnection
{
// private set is legal now, it is not part of the interface
string ConnectionString { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
我知道如何解决这个问题,因为同时拥有一个显式和隐式接口是合法的,而且我可以使隐式接口实现完全私有.
然而,我想知道这背后的原因.因为从技术上讲,内部编译的私有方法set_IConnection_ConnectionString不需要是接口的一部分,对吧?它可以被视为辅助setter,而不是接口的一部分,因为它处于隐式实现情况中.
更新:作为奖励,看似令人困惑,在我看来不太正确的编译错误,您收到的是以下内容:
访问者的可访问性修饰符必须比属性Connection1.ConnectionString更具限制性
请问,更严格的比private,怎么......什么?
更具体地说,如果我有:
public class TempClass : TempInterface
{
int TempInterface.TempProperty
{
get;
set;
}
int TempInterface.TempProperty2
{
get;
set;
}
public int TempProperty
{
get;
set;
}
}
public interface TempInterface
{
int TempProperty
{
get;
set;
}
int TempProperty2
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用反射来获取显式实现TempInterface的属性的所有propertyInfos?
谢谢.
我使用的是FtpWebResponse类,但没有看到Dispose方法. 事实证明,该类实现了IDisposable,但是明确地这样做,因此在调用Dispose之前必须先将实例强制转换为IDisposable:
// response is an instance of FtpWebResposne
((IDisposable) response).Dispose();
Run Code Online (Sandbox Code Playgroud)
为什么像这样的类的设计者会选择明确地实现IDisposable?正如Anthony Pegram所说,以这种方式做事掩盖了这样一个事实,即对象应该为每次使用课程时都没有查阅文档的普通开发人员处理.
public abstract class EntityBase { ... }
public interface IFoobar
{
void Foo<T>(int x)
where T : EntityBase, new();
}
public interface IFoobar<T>
where T : EntityBase, new()
{
void Foo(int x);
}
public class Foobar<T> : IFoobar, IFoobar<T>
where T : EntityBase, new()
{
public void Foo(int x) { ... }
void IFoobar.Foo<T>(int x) { Foo(x); }
}
Run Code Online (Sandbox Code Playgroud)
我收到编译器警告: Type parameter 'T' has the same name as the type parameter from outer type '...'
我尝试过:void IFoobar.Foo<U>(int x) { …
我从以下属性收到编译错误.
错误是:
"修饰符'public'对此项无效"
public System.Collections.Specialized.StringDictionary IWorkItemControl.Properties
{
get { return properties; }
set { properties = value; }
}
Run Code Online (Sandbox Code Playgroud)
但如果我删除IWorkItemControl它编译好.
为什么我收到此错误,签名中是否有/没有接口名称有什么区别?
我的问题与此问题有些相关:泛型约束如何阻止使用隐式实现的接口对值类型进行装箱?,但不同,因为它不需要约束来执行此操作,因为它根本不是通用的.
我有代码
interface I { void F(); }
struct C : I { void I.F() {} }
static class P {
static void Main()
{
C x;
((I)x).F();
}
}
Run Code Online (Sandbox Code Playgroud)
主要方法编译如下:
IL_0000: ldloc.0
IL_0001: box C
IL_0006: callvirt instance void I::F()
IL_000b: ret
Run Code Online (Sandbox Code Playgroud)
为什么不编译到这个?
IL_0000: ldloca.s V_0
IL_0002: call instance void C::I.F()
IL_0007: ret
Run Code Online (Sandbox Code Playgroud)
我明白为什么你需要一个方法表来进行虚拟调用,但在这种情况下你不需要进行虚拟调用.如果接口正常实现,则不进行虚拟呼叫.
还相关:为什么显式接口实现是私有的? - 关于这个问题的现有答案没有充分解释为什么这些方法在元数据中被标记为私有(而不是仅仅具有不可用的名称).但即使这样也没有完全解释为什么它是盒装的,因为从C里面调用时它仍然是盒子.
虽然IDisposable在SO上有相当多的问答,但我还没有找到答案:
我通常遵循这样的做法:当我的一个类拥有一个IDisposable对象时,它也实现IDisposable并调用Dispose拥有的对象.但是最近我遇到了一个IDisposable明确实现的类,因此阻止我直接Dispose强制我强制转换它,我觉得这很烦人且没必要.
所以问题是:为什么以及何时想要使用显式接口实现IDisposable?我知道明确地实现接口有完全正确和有效的理由但是对于IDisposable我来说不明确的原因.
为什么在具有接口类型约束的泛型方法中的显式C#接口调用总是调用基本实现?
例如,请考虑以下代码:
public interface IBase
{
string Method();
}
public interface IDerived : IBase
{
new string Method();
}
public class Foo : IDerived
{
string IBase.Method()
{
return "IBase.Method";
}
string IDerived.Method()
{
return "IDerived.Method";
}
}
static class Program
{
static void Main()
{
IDerived foo = new Foo();
Console.WriteLine(foo.Method());
Console.WriteLine(GenericMethod<IDerived>(foo));
}
private static string GenericMethod<T>(object foo) where T : class, IBase
{
return (foo as T).Method();
}
}
Run Code Online (Sandbox Code Playgroud)
此代码输出以下内容:
IDerived.Method
IBase.Method
而不是人们可能期望的:
IDerived.Method
IDerived.Method
似乎没有办法(缺少反射)来调用在运行时决定的类型的隐藏的,更加派生的显式接口实现.
编辑:要清楚,如果检查在上面的GenericMethod调用中计算结果为true: …
我需要能够确定给定的方法或属性是否来自特定接口并且是否明确实现.
有没有人这样做,是否有可能通过.NET反射获取此信息?
更新
从下面的评论中可以看出接受的答案,我想要实现的实际事情是通过反射调用实现特定接口的方法.由于可能有多个具有相同方法签名的接口,我想确定基于接口调用的正确实现.在我的场景中,实现类型,接口和方法名称是在运行时确定的,所以我不能在我的情况下使用简单的转换.
我有一个令人烦恼的错误.
type Animal =
abstract member Name : string
type Dog (name : string) =
interface Animal with
member this.Name : string =
name
let pluto = new Dog("Pluto")
let name = pluto.Name
Run Code Online (Sandbox Code Playgroud)
最后一行,特别是"Name"生成编译器错误,指出"未定义字段,构造函数或成员'Name'".
我用过的解决方法是写
let name = (pluto :> Animal).Name
Run Code Online (Sandbox Code Playgroud)
然而,这非常烦人并且产生许多视觉噪音.是否可以在F#中执行某些操作以便能够解析Name而不会明确告诉编译器Name是Animal类型的派生成员?
f# overloading interface explicit-interface overload-resolution
c# ×9
interface ×5
.net ×4
generics ×2
idisposable ×2
reflection ×2
boxing ×1
constraints ×1
f# ×1
inheritance ×1
overloading ×1