我有一個實現接口的對象。如果它被實現,我想調用對象的方法。這樣做的最好方法是什麼?C#:可選方法
更新 你們幾個人提到我的問題含糊不清。對於那個很抱歉。當我說「如果實施」我的意思是「如果它是可調用的」。感謝你的回答和努力人(或女孩!)。我很驚訝這個網站上有多少開發者支持。
我有一個實現接口的對象。如果它被實現,我想調用對象的方法。這樣做的最好方法是什麼?C#:可選方法
更新 你們幾個人提到我的問題含糊不清。對於那個很抱歉。當我說「如果實施」我的意思是「如果它是可調用的」。感謝你的回答和努力人(或女孩!)。我很驚訝這個網站上有多少開發者支持。
如果這真的是你需要它的工作方式,那麼界面是錯誤的選擇。相反,你可以有一個抽象類,從你的類派生出一個虛擬方法。虛擬允許它被覆蓋,但不需要它。由於虛擬方法具有實現,因此它不能成爲接口的一部分。
不太清楚你的意思是「如果它被實現」。如果該方法在接口中並且您的對象實現了接口,則它必須實現該方法。
該對象的類不應該實現接口的每個方法嗎?
如果對象的類繼承自一個抽象類,它可能不會覆蓋(「實現」)某些方法。也許你正在混淆你的想法。
創建兩個接口,並繼承需要所有方法的兩個接口。只繼承其中一個接口,其中不需要可選方法。 您也可以創建一個基礎接口,從中您可以繼承所有接口,以供OOP使用。
如果你想測試一個對象實現了接口,這樣你就可以調用該方法,你能做到像這樣:
interface IFoo { void Bar(); }
object o = GetObjectThatMayImplementIFoo();
IFoo foo = o as IFoo;
if (foo != null) {
foo.Bar();
}
我認爲這是你問的是什麼?
與其他答案一樣,我不確定你的意思。實現接口的類最接近不能實現其中一種接口方法的方法是拋出NotImplementedException。處理這種情況的方法是在調用該方法時專門捕獲該異常。但是,接口的全部要點是定義類之間的契約,所以也許一些澄清會有所幫助。
你不能真正知道該方法是否實際實現(或者該類只有一個「虛擬」實現)。因此,您可以使用以下模式之一來確定是否支持特定的方法:
- >有多個接口並查看該類是否實際實現了它;這可能是對付它最乾淨的方式,但它可能讓你有大量不同的接口,這可能是不希望:
IIntfA = inst as IIntfA;
if (inst != null) {
// inst seems to be implemented
}
- 在TryXxx風格>使用方法,它會返回如果屬實他們是成功的(如TryParse()
等)。
- >使用NotImplementedException
- 但請注意,捕獲這些代碼非常昂貴,應該僅用於很少執行的調用,或者預期不會執行缺少的調用。 Stream
類的工作原理是這樣的,例如,如果它不能寫入(但另外還有一個屬性,告訴類支持什麼,例如Stream
類中的IsWritable
)。
你錯過了變量名 – 2009-10-28 19:17:15
我的第一反應是不要這樣做。它創建了條件邏輯圍繞方法存在的可能性,它違背了C#的靜態類型並打破了一些SOLID原則。我的經歷告訴我這是走錯路的錯誤。
這樣說可以通過反射或使用wojo演示的'is/as'解決方案來完成。
這種類型的行爲可能更好地用動態語言實現。這聽起來與鴨子打字相似。我不是一個充滿活力的語言傢伙,但是如果你有單元測試的話,它可能是沒問題的。
嘿,夥計們,不要忘了「是」關鍵詞:P
如果一個對象實現過這樣的界面可以查看:
if (inst is IInterface)
{
// you can safely cast it
}
我喜歡你這樣,當然,但你也可以使用「as」關鍵字
IInterface a = inst as IInterface;
if (a != null)
{
// use a, already casted
}
我認爲你真正想要的是一種部分方法。這些在.NET 3.5中是新的。您只需申報方法「部分」:
partial void OnLoaded();
該方法可以正常調用:
OnLoaded();
整潔的事情是,如果該方法沒有在任何地方實現,編譯器是足夠聰明,不生成呼叫。
這主要是爲LINQ to SQL和Entity Framework實現的;這允許生成的代碼(使用部分類)定義和調用方法,而不知道它們是否已實現。
用接口混合部分方法會很有趣(我沒有嘗試過),但是我的第一次嘗試是在接口中聲明一個部分方法。
+1。這個答案也是我的直覺。 – Brian 2009-10-28 19:29:00
我懷疑這就是他需要的。部分方法應該用於在同一類的兩個部分之間建立可選的「回調」(其中一個通常是生成的,另一個是手動編碼的)。它們有很多限制 - 僅限於私有,無效返回等。它們絕對與接口無關。 – 2009-10-28 20:04:33
它們當然是爲了在部分類中使用生成的代碼而創建的。我們對原始海報的要求沒有足夠的信息來了解這是否合適。也可以將屬性設置爲私有方法的訪問器,因此「私有」不一定是缺點。 (就此而言,財產可能是解決問題的另一種方法。) – 2009-10-28 20:11:01
我不知道你是否正在尋找這樣的東西。這使用一個屬性,您可以標記一個方法是否實現。接下來,我向接口添加了一個擴展方法,以檢查是否實現了方法。最後,代碼將允許您詢問對象是否實現了該方法。我不喜歡這個,但它可能是你正在尋找的東西。
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();
}
}
編輯:原作者重寫問題後,你絕對只是想實現接口保證該方法確實存在。爲了好奇,我會留下上面的代碼。
Aww謝謝!非常有趣的解決方案。 – burnt1ce 2009-10-29 19:02:19
根據您引用對象的方式,某些成員將可見。接口可能是隱式定義的或明確定義的,也可能是由派生類實現的,並且您使用的是基類引用。換句話說,對象上的所有可用成員並不總是立即顯現出來。
所以,如果你想測試你的對象(yourObj)的某個接口(ISomething)的實現,一種選擇是使用反射測試數據類型。根據此測試的結果,您可以明確地將實現對象轉換爲接口類型並使用其成員...
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 - 從你選擇的對象,那麼你的對象實現了這個接口,因此有這些公共成員。
子類仍然會有一個虛擬的方法實現。這將是基類的實現。 – 2009-10-28 22:34:40