我有一个实现接口的对象。如果它被实现,我想调用对象的方法。这样做的最佳方式是什么?
更新 你们中的一些人提到我的问题很模糊。对于那个很抱歉。当我说“如果它被实现”我的意思是“如果它是可调用的”。谢谢你的回答和努力的家伙(或女孩!)。我很惊讶这个网站上有多少开发者支持。
答案 0 :(得分:13)
如果这真的是你需要它的方式,接口是错误的选择。相反,您可以拥有一个抽象类,您的类可以使用虚拟方法从中派生。 Virtual允许覆盖它,但不需要它。由于虚方法具有实现,因此它不能是接口的一部分。
答案 1 :(得分:12)
不确定“是否实施”是什么意思。如果方法在接口中并且您的对象实现了接口,则它必须实现该方法。
答案 2 :(得分:10)
如果你想测试一个对象是否实现了接口以便你可以调用该方法,你可以这样做:
interface IFoo { void Bar(); }
object o = GetObjectThatMayImplementIFoo();
IFoo foo = o as IFoo;
if (foo != null) {
foo.Bar();
}
我认为这就是你的要求?
答案 3 :(得分:7)
创建两个接口,并继承需要所有方法的两个接口。仅继承其中一个不需要可选方法的接口。 您也可以创建一个基本接口,所有接口都将从该接口继承,以供OOP使用。
答案 4 :(得分:4)
我认为你真正想要的是一种局部方法。这些是.NET 3.5中的新功能。您只需将方法声明为“部分”:
partial void OnLoaded();
该方法可以正常调用:
OnLoaded();
巧妙的是,如果方法没有在任何地方实现,编译器就足够聪明,不会生成调用。
这主要是为LINQ to SQL和Entity Framework实现的;这允许生成的代码(使用部分类)定义和调用方法,而无需知道它们是否已实现。
将部分方法与接口混合会很有趣(我还没有尝试过),但我的第一次尝试是在界面中声明一个部分方法。
答案 5 :(得分:2)
对象的类不应该实现接口的每个方法吗?
如果对象的类继承自抽象类,则可能不会覆盖(“实现”)某些方法。也许你想把两者混合起来。
答案 6 :(得分:2)
与其他答案一样,我不确定你的意思。实现接口的类可能无法实现其中一个接口方法的最接近的是抛出NotImplementedException。处理此问题的方法是在调用方法时专门捕获该异常。但是,接口的重点是定义类之间的契约,所以也许一些澄清会有所帮助。
答案 7 :(得分:2)
我的第一反应是不要这样做。它围绕方法存在的可能性创建条件逻辑,它违背了C#的静态类型,并打破了一些SOLID原则。我的经验告诉我这是走错路。
据说它可以通过Reflection或使用'is / as'解决方案来完成,并表示。
这种行为可能更好地用动态语言实现。这听起来像鸭子打字。我不是一个动态的语言人,但如果你有单元测试,它可能没问题。
答案 8 :(得分:1)
您无法真正知道该方法是否实际实现(或者该类是否只有“虚拟”实现)。因此,您可以使用以下某种模式来确定是否支持特定方法:
- >有多个接口,看看类是否实际实现了它;这可能是处理它的最简洁的方法,但它可能会留下大量不同的接口,这可能是不可取的:
IIntfA = inst as IIntfA;
if (inst != null) {
// inst seems to be implemented
}
- >使用TryXxx样式中的方法,如果成功则返回true(如TryParse()
等)。
- >使用NotImplementedException
- 但请注意,捕获它们非常昂贵,并且只应用于很少执行的调用,或者不期望丢失实现的调用。 Stream
类的工作方式如下,例如,如果无法写入(但另外还有一个属性可以告诉类支持的内容,例如IsWritable
类中的Stream
。) p>
答案 9 :(得分:1)
嘿伙计们,不要忘记“是”关键字:P
您可以检查对象是否也实现了这样的界面:
if (inst is IInterface)
{
// you can safely cast it
}
我更喜欢它,但当然你也可以使用“as”关键字
IInterface a = inst as IInterface;
if (a != null)
{
// use a, already casted
}
答案 10 :(得分:0)
我不知道你是否正在寻找这样的东西。这使用一个属性,您可以使用该方法标记方法是否已实现。接下来,我向接口添加了一个扩展方法,以便检查它是否已实现。最后,代码将允许您询问对象是否已实现该方法。我不喜欢这个,但它可能就是你要找的东西。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ConsoleApplication1
{
public static class Program
{
static void Main(string[] args)
{
EmployeeA empA = new EmployeeA();
if (empA.IsImplemented("TestMethod"))
empA.TestMethod();
EmployeeB empB = new EmployeeB();
if (empB.IsImplemented("TestMethod"))
empB.TestMethod();
Console.ReadLine();
}
public static bool IsImplemented(this IEmp emp, string methodName)
{
ImplementedAttribute impAtt;
MethodInfo info = emp.GetType().GetMethod(methodName);
impAtt = Attribute.GetCustomAttribute(info, typeof(ImplementedAttribute), false)
as ImplementedAttribute;
return (impAtt == null) ? true : impAtt.Implemented;
}
}
public class EmployeeA : IEmp
{
#region IEmp Members
[Implemented(false)]
public void TestMethod()
{
Console.WriteLine("Inside of EmployeeA");
}
#endregion
}
public class EmployeeB : IEmp
{
#region IEmp Members
[Implemented(true)]
public void TestMethod()
{
Console.WriteLine("Inside of EmployeeB");
}
#endregion
}
public class ImplementedAttribute : Attribute
{
public bool Implemented { get; set; }
public ImplementedAttribute():this(true)
{
}
public ImplementedAttribute(bool implemented)
{
Implemented = implemented;
}
}
public interface IEmp
{
void TestMethod();
}
}
编辑:在原作者改写问题之后,你肯定只想实现保证该方法确实存在的界面。为了好奇,我将保留上面的代码。
答案 11 :(得分:0)
根据您引用对象的方式,某些成员将可见。接口可能是隐式定义或显式定义的,或者可能由派生类实现,并且您正在使用基类引用。换句话说,它并不总是立即显示对象上的所有可用成员。
因此,如果您想通过对象(yourObj)测试某个接口(ISomething)的实现,可以选择使用反射来测试数据类型。根据此测试的结果,您可以将实现对象显式地转换为接口Type并使用其成员...
if (yourObj is ISomething)
((ISomething)yourObj).DoSomething();
这是另一种方式(使用方法调用更“罗嗦”):
if (typeof(ISomething).IsAssignableFrom(yourObj.GetType()))
((ISomething)yourObj).DoSomething();
此示例假定ISomething接口定义为:
public interface ISomething {
void DoSomething();
// other members ...
}
总之,这段代码说:如果接口ISomething Is-Assignable - 从您选择的对象,那么您的对象实现该接口,因此具有这些公共成员。