Essentially, what we've got is this:
public class A {
...
public A() { ... }
...
}
public class B : A {
...
public B() : base()
{ throw new Exception(); }
...
}
But then:
public class Test<T>
where T : A, new()
{
public void doStuff() { B b = new B(); }
}
And no exception is thrown. It's really quite confusing! Am I missing something?
The following code throws an exception as intended. I imagine you aren't using your Test class correctly since you didn't post the code.
public MainWindow()
{
InitializeComponent();
Test<B> myTest = new Test<B>();
myTest.doStuff(); // throws exception in B()
}
public class A
{
public A() { }
}
public class B : A
{
public B()
: base()
{
throw new Exception();
}
}
public class Test<T> where T : A, new()
{
// I modified this because the intent is to use T correct?
public void doStuff() { T test = new T(); }
}
Related
I wonder if something like this is possible in C#:
public class A
{
public string Foo() { return "Foo"; }
}
public class B : A
{
public string Bar() { return Foo(); }
}
public class C : B
{
public new string B.Foo() { return "Bar"; } // Hide A.Foo in B
}
Main()
{
C c = new C();
Console.WriteLine(c.Bar()); // Want to get "Bar"
}
by public new string B.Foo() { return "Bar"; } I mean do something in C (without changing A or B) that has the equivalent result as if public new string Foo() { return "Bar"; } was implemented in B. So, hide a method FOR a base class OF a base further up the inheritance hierarchy.
What you want is virtual, which allows you to override base behavior in the inheriting type.
public class A
{
public virtual string Foo() { return "Foo"; }
}
public class B : A
{
public virtual string Bar() { return Foo(); }
}
public class C : B
{
public override string Foo() { return "Bar"; } // Hide A.Foo in B
}
This outputs "bar"
Please see this structure (from here):
public abstract class AbstractPage<T> where T : AbstractPageEmenetsMap, new()
{
protected readonly string url;
protected VendorInfo vendorInfo;
public AbstractPage(VendorInfo vendorInfo)
{
this.vendorInfo = vendorInfo;
this.url = this.vendorInfo.Url;
}
public void Navigate()
{
WebDriver.Driver.Navigate().GoToUrl(this.url);
}
protected T Map
{
get { return new T(); }
}
}
public abstract class AbstractPage<M, V> : AbstractPage<M>, ITest
where M : AbstractPageEmenetsMap, new()
where V : AbstractPageValidator<M>, new()
{
public AbstractPage(VendorInfo vendorInfo)
: base(vendorInfo) { }
public V Validate()
{
return new V();
}
public void Login();
{
throw new System.NotImplementedException();
}
public void Logout();
{
throw new System.NotImplementedException();
}
}
And i want to add interface with some operations
public interface ITest
{
void Login();
void Logout();
}
Now this is Son class:
public class GmailPage : AbstractPage<GmailPageElementsMap, GmailPageValidator>, ITest
{
public GmailPage() : base("http:...") { }
}
Class that holds all the elements:
public IWebElement EmailAddressTextBox
{
get
{
return WebDriver.WebDriverWait.Until(ExpectedConditions.ElementIsVisible(By.Id("identifierId")));
}
}
And validator:
public class GmailPageValidator : AbstractPageValidator<GmailPageElementsMap>
{
}
As you can see i implement ITest from my Gmail class but i don't received any compile error although i do not add this 2 interface methods (Login and Logout).
This is because those methods are implemented in the parent AbstractPage. If you want to force GmailPage (and all other derived classes) to implement Login() and Logout() declare them as abstract in the parent AbstractPage class
public abstract class AbstractPage<M, V> : AbstractPage<M>, ITest
where M : AbstractPageEmenetsMap, new()
where V : AbstractPageValidator<M>, new()
{
public AbstractPage(VendorInfo vendorInfo) : base(vendorInfo) { }
public V Validate()
{
return new V();
}
public abstract void Login();
public abstract void Logout();
}
And override in GmailPage
public class GmailPage : AbstractPage<GmailPageElementsMap, GmailPageValidator>
{
public GmailPage() : base("http:...") { }
public override void Login()
{
throw new System.NotImplementedException();
}
public override void Logout()
{
throw new System.NotImplementedException();
}
}
I have a problem with abstract class and generic in c# (I usually code in Java) : here is the code I would like to use :
public interface InterfaceResult {...}
public abstract class Result : InterfaceResult {...}
public class ResultA : Result {...}
public class ResultB : Result {...}
public interface InterfaceKing { InterfaceResult function();}
public abstract class King : InterfaceKing {
public abstract Result function();
}
public class KingA : King {
public override ResultA function(){...}
}
public class KingB : King {
public override ResultB function(){...}
}
but that doesn t work : Visual Studio want for KingA and KingB to return an instance of Result with function(). If i use "new" instead of override, VS say I don t implement the required method (i need to use override).
So I tried with generic and it s not better
public abstract class Result { }
public class ResultA : Result { }
public class ResultB : Result { }
public interface IKing<T> {T function(); }
public abstract class King<Result> : IKing<Result>
{
public abstract Result function();
public static implicit operator King<Result>(KingB v)
{
return v; // generate StackOverflow Exception
}
public static implicit operator King<Result>(KingA v)
{
throw new NotImplementedException();
}
}
public class KingA : King<ResultA>
{
public override ResultA Get()
{
return new ResultA();
}
}
public class KingB : King<ResultB>
{
public override ResultB Get()
{
return new ResultB();
}
}
public class Test
{
King<Result> a = new KingA(); // allowed by public static implicit operator King<Result>(KingA v)
King<Result> b = new KingB(); // allowed by public static implicit operator King<Result>(KingB v)
KingA ka = new KingA();
List<King<Result>> lista = new List<King<Result>>();
public void test()
{
lista.Add(ka);
}
}
How can i make this work ? I can t find any solution nor any good or complete example.
Moving from "full interface" to "no interface" (for lack of better terms) all that work (this Main works fine)
static void Main ()
{
King a = new KingA ();
King b = new KingB ();
KingA ka = new KingA ();
List<King> list = new List<King> ();
list.Add (a);
list.Add (b);
list.Add (ka);
}
"full interface"
public interface InterfaceResult { }
public abstract class Result : InterfaceResult { }
public class ResultA : Result { }
public class ResultB : Result { }
public interface InterfaceKing { InterfaceResult Function (); }
public abstract class King : InterfaceKing
{
public abstract InterfaceResult Function ();
}
public class KingA : King
{
public override InterfaceResult Function () => new ResultA ();
}
public class KingB : King
{
public override InterfaceResult Function () => new ResultA ();
}
"mixed (less interface)"
public abstract class Result { }
public class ResultA : Result { }
public class ResultB : Result { }
public interface IKing { Result Function (); }
public abstract class King : IKing
{
public abstract Result Function ();
}
public class KingA : King
{
public override Result Function () => new ResultA ();
}
public class KingB : King
{
public override Result Function () => new ResultB ();
{
return new ResultB ();
}
}
"no interface"
public abstract class Result { }
public class ResultA : Result { }
public class ResultB : Result { }
public abstract class King
{
public abstract Result Function ();
}
public class KingA : King
{
public override Result Function () => new ResultA ();
}
public class KingB : King
{
public override Result Function () => new ResultB ();
}
Using covariance
See .net fiddler here. Read more about Covariance and Contravariance
public abstract class Result { }
public class ResultA : Result { }
public class ResultB : Result { }
public interface IKing<out T> where T : Result {}
public abstract class King<T> : IKing<T> where T : Result
{
public abstract T Get();
}
public class KingA : King<ResultA>
{
public override ResultA Get()
{
return new ResultA();
}
}
public class KingB : King<ResultB>
{
public override ResultB Get()
{
return new ResultB();
}
}
public class TestClass
{
King<ResultA> a = new KingA(); // allowed by public static implicit operator King<Result>(KingA v)
King<ResultB> b = new KingB(); // allowed by public static implicit operator King<Result>(KingB v)
KingA ka = new KingA();
List<IKing<Result>> lista = new List<IKing<Result>>();
public void Test()
{
lista.Add(ka);
}
}
Is it possible to cast T in the line new ConsumeA1<T> (); to A1?
With the current code I'm getting the error:
Type 'T' cannot be used as parameter 'T' in the generic type or method 'ConsumeA1'. There is no boxing conversion or type parameter conversion from 'T' to 'A1'
class Consume<T> where T : A
{
public Consume()
{
if (typeof(T) == typeof(A1))
{
new ConsumeA1<T> ();
}
if (typeof(T) == typeof(A))
{
new ConsumeA<T>();
}
}
}
class ConsumeA<T> where T : A
{
}
class ConsumeA1<T> where T : A1
{
}
interface A
{
}
interface A1 : A
{
}
class Imp1 : A
{
}
class Imp2 : A1
{
}
// ....
class ImpN : A
{
}
There is not point in using generics if you want to cast to a concrete type...
From what I understand all your concrete types contain a Consume() functionality
You can move this method to be part of your A interface.
Then,you don't need a Consume< T> class.
You can just use a method that accepts a A as a parameter and calls Consume()
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
A obj = new Imp1();
Consume(obj);
obj = new Imp2();
Consume(obj);
obj = new ImpN();
Consume(obj);
Console.ReadLine();
}
static void Consume(A a) { a.Consume(); }
}
interface A { void Consume(); }
interface A1 : A { }
class Imp1 : A { public void Consume(){ Console.WriteLine("Imp1"); } }
class Imp2 : A1 { public void Consume(){ Console.WriteLine("Imp2"); } }
class ImpN : A { public void Consume(){ Console.WriteLine("ImpN"); } }
}
Now if you need something similar to your sample code you can use generic constraints
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Consume<Imp1>.ConsumeObject();
Consume<Imp2>.ConsumeObject();
Consume<ImpN>.ConsumeObject();
Console.ReadLine();
}
}
class Consume<T> where T : A, new()
{
static public void ConsumeObject()
{
new T();
}
}
class ConsumeA<T> where T : A { }
class ConsumeA1<T> where T : A1 { }
interface A { }
interface A1 : A { }
class Imp1 : A { public Imp1() { Console.WriteLine("Imp1"); } }
class Imp2 : A1 { public Imp2() { Console.WriteLine("Imp2"); } }
class ImpN : A { public ImpN() { Console.WriteLine("ImpN"); } }
}
or with fewer lines of code
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
new Consume<Imp1>();
new Consume<Imp2>();
new Consume<ImpN>();
}
}
class Consume<T> where T : A, new() { public Consume() { new T(); } }
interface A { }
interface A1 : A { }
class Imp1 : A { public Imp1() { System.Console.WriteLine("Imp1"); } }
class Imp2 : A1 { public Imp2() { System.Console.WriteLine("Imp2"); } }
class ImpN : A { public ImpN() { System.Console.WriteLine("ImpN"); } }
}
or without the Consume< T >class
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Consume<Imp1>();
Consume<Imp2>();
Consume<ImpN>();
System.Console.ReadLine();
}
private static void Consume<T>() where T : A, new() { new T(); }
}
interface A { }
interface A1 : A { }
class Imp1 : A { public Imp1() { System.Console.WriteLine("Imp1"); } }
class Imp2 : A1 { public Imp2() { System.Console.WriteLine("Imp2"); } }
class ImpN : A { public ImpN() { System.Console.WriteLine("ImpN"); } }
}
I've this class structure:
namespace ClassLibrary1
{
public interface IComponentGuid { }
class ComponentGuid : IComponentGuid{}
internal interface IComponent<T> where T : IComponentGuid {
List<T> List();
}
class SpecificComponent : IComponent<ComponentGuid> {
public List<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
}
class P
{
public P(IComponent<IComponentGuid> pComponent) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}
The problem arise instantiating P: var p = new P(specific);
I get a
cannot convert from 'ClassLibrary1.SpecificComponent' to 'ClassLibrary1.IComponent<ClassLibrary1.IComponentGuid>'
What am I doing wrong?
Thank you.
You can make it work if you forgo List<T> on your interface and replace it with a co-variant interface of IEnumerable<T> and then make your type parameter co-variant as well:
namespace ClassLibrary1
{
public interface IComponentGuid { }
class ComponentGuid : IComponentGuid{}
internal interface IComponent<out T> where T : IComponentGuid {
IEnumerable<T> List();
}
class SpecificComponent : IComponent<ComponentGuid> {
public IEnumerable<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
}
class P
{
public P(IComponent<IComponentGuid> pComponent) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}
I'm trying this solution splitting the IComponent interface into two, one covariant and one invariant.
namespace ClassLibrary1
{
public interface IComponentGuid { }
public class ComponentGuid : IComponentGuid { }
public interface IComponentBase<out T> where T : IComponentGuid
{
IEnumerable<T> List();
}
interface IComponent<T>
{
void AddToList(T item );
}
public class SpecificComponent : IComponentBase<ComponentGuid>, IComponent<ComponentGuid>
{
public IEnumerable<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
public void AddToList(ComponentGuid item)
{
throw new System.NotImplementedException();
}
}
public class P
{
public P(IComponentBase<IComponentGuid> pComponentBase) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}