Reputation: 501
I want to define an object
and make instance of it to other class, but I can't call the method, here's my code:
class Test1
{
public bool True_1()
{return true;}
}
class Test2
{
public bool True_2()
{return true;}
}
class MainClass
{
static void Main()
{
object a;
bool flag = true; // or false
if (flag)
a = new Test1();
else
a = new Test2();
if (a is Test1)
a.True_1(); //error before compiling
else
a.True_2(); //error before compiling
}
}
}
I know there's a way of creat an interface I_Test
, and do this:
class Test1:I_Test
class Test2:I_Test
but since class Test2
is a dll from third-party so I can't add :I_Test
to it,
so I want to make my code here achievable, any suggestion? thx!
Upvotes: 0
Views: 102
Reputation: 12851
You can do these two solutions to solve this problem:
1. Convert a
to the class that you want and then you can call the method: Try this:
static void Main()
{
object a;
bool flag = true;
if (flag)
a = new Test1();
else
a = new Test2();
if (a is Test1)
{
((Test1)a).True_1(); //So, there will be no error anymore
}
else
{
((Test2)a).True_2();
}
}
use dynamic
keyword instead of object
type. Try this:
static void Main()
{
dynamic a;
bool flag = true;
if (flag)
a = new Test1();
else
a = new Test2();
if (a is Test1)
a.True_1(); //So, there will be no error anymore
else
a.True_2();
}
Upvotes: 1
Reputation: 250336
If you are using the C# 7 you can use the new syntax that allows you to test and put the result of the test into a variable in a single line :
if (a is Test1 aTest)
aTest.True_1();
else if( a is Test2 aTest2)
aTest2.True_2();
If you are using older C# you can use the as
operator coupled with a null test :
var aTest = a as Test1;
if (aTest != null)
aTest.True_1();
else
{
var aTest2 = a as Test2;
if (aTest2 != null)
{
aTest2.True_2();
}
}
You can also use a test and cast solution which minimizes the amount of variables, this is not recommended as that may forces the runtime to test twice (once for is
and once for the cast). See this question for a more detailed response
if(a is Test1)
((Test1)a).True_1();
Upvotes: 1
Reputation: 52290
Let's say you have a third party DLL that contains a class...
class ThirdPartyClass
{
public bool Foo { get { return true;} }
}
And you want to create your own class that has a method or property in common with the third party class:
class MyClass
{
public bool Foo { get { return true;} }
}
As you mention, what you'd normally do is add an interface to the third party class, and then implement that interface in your own class. But you can't do that, as you also pointed out. And without an interface in common, you're stuck with that clunky if/then construct.
If I correctly understand your situation, you can deal with it as follow. Extend the third party class to add the interface, like so:
interface IMyInterface
{
bool Foo { get; }
}
class MyThirdPartyClass : ThirdPartyClass, IMyInterface
{
}
Since Foo
is public, it will get inherited and be available, and satisfy the interface. And now you can create your own class too:
class MyClass : IMyInterface
{
public bool Foo { get { return true; }}
}
And you can use them interchangeably:
IMyInterface a = new MyThirdPartyClass();
IMyInterface b = new MyClass();
bool c = a.Foo;
bool d = b.Foo;
That's how I would do it.
You may run into a problem if the third party class is sealed. If that is the case, you have to wrap it instead of inheriting from it:
class MyThirdPartyClassWrapper : IMyInterface
{
private readonly ThirdPartyClass _wrappedInstance = new ThirdPartyClass();
public bool Foo { get { return _wrappedInstance.Foo; } }
}
And then it'll still work:
IMyInterface a = new MyThirdPartyClassWrapper();
IMyInterface b = new MyClass();
bool c = a.Foo;
bool d = b.Foo;
Upvotes: 0
Reputation: 3925
You have to cast it first
if(a is Test1 aConverted)
aConverted.True_1();
Or older way of doing this:
if(a is Test1)
((Test1)a).True_1();
Upvotes: 0