|
The way I tend to code this type of code is to have an instance method call the override versions, like this:
public abstract class MyBase
{
public MyBase()
{
Initialize();
}
private void Initialize()
{
OnInitialize();
}
protected virtual void OnInitialize()
{
}
} Why do I do this you may ask? Well, I tend to have a separation of design time code, and runtime code, and this allows me to easily separate things out.
|
|
|
|
|
Does that dodge the warning? If so, that's pretty rubbish on FXCop's part since that's 'bad' for exactly the same reason.
|
|
|
|
|
Yes it does, and there's nothing wrong with doing this. The problem with FxCop is that it's very arbitrary with its rules, many of which are excessively anal.
|
|
|
|
|
I'll check this later - I'm pretty sure on VS2012 when I tried this yesterday before posting it just added something into the warning about a call chain or similar but still CA2214
|
|
|
|
|
In VS2012 you still get the warning
contains a call chain that results in a call to a virtual method defined by the class
|
|
|
|
|
DaveyM69 wrote: The overridden method is purely setting instance fields unique to that class to
their initial values (these are not changed anywhere after instanciation - that
part of the derived classes is immutable) and returning initialization values
that are common to all derived classes to the base's constructor.
As I read that...
Yes that can lead to problems.
And that is what the constructor is supposed to do - iniatialize the class variables.
Also why would the base ctor care about child initialization values when all the base ctor should be doing is initializing the base ctor?
|
|
|
|
|
jschell wrote: why would the base ctor care about child initialization values when all the base
ctor should be doing is initializing the base ctor
The child needs to self initialize with values retrieved from an unmanaged function call (the function is different for each child type) - then pass the common values to the base so it can initialize itself.
What I was trying to do was force a method to be called when the base constructor runs that
1. calls the unmanaged function (hence it needing to be in called from the child as only the child should know what unmanaged function to call, and therefore needs to be an abstract method)
2. the child initializes it's unique fields
3. passes the common values back into the base constructor (hence the out parameters)
Perhaps this code will make it clearer...
public abstract class Base
{
private int commonValue1;
private int commonValue2;
private int id;
protected Base(int id)
{
this.id = id;
Initialize(out commonValue1, out commonValue2);
}
public int CommonValue1
{
get { return commonValue1; }
}
public int CommonValue2
{
get { return commonValue2; }
}
public int Id
{
get { return id; }
}
protected abstract void Initialize(out int commonValue1, out int commonValue2);
}
public class ChildA : Base
{
public ChildA(int id)
: base(id)
{ }
protected override void Initialize(out int commonValue1, out int commonValue2)
{
DataA data;
NativeMethods.UnmanagedFunctionGetChildAData(Id, out data);
commonValue1 = data.Value1;
commonValue2 = data.Value2;
}
}
public class ChildB : Base
{
private int childBValue;
public ChildB(int id)
: base(id)
{ }
public int ChildBValue { get { return childBValue; } }
protected override void Initialize(out int commonValue1, out int commonValue2)
{
DataB data;
NativeMethods.UnmanagedFunctionGetChildBData(Id, out data);
commonValue1 = data.Value1;
commonValue2 = data.Value2;
childBValue = data.Value3;
}
}
public class ChildC : Base
{
private int childCValue1;
private int childCValue2;
public ChildC(int id)
: base(id)
{ }
public int ChildCValue1 { get { return childCValue1; } }
public int ChildCValue2 { get { return childCValue2; } }
protected override void Initialize(out int commonValue1, out int commonValue2)
{
DataC data;
NativeMethods.UnmanagedFunctionGetChildCData(Id, out data);
commonValue1 = data.Value1;
commonValue2 = data.Value2;
childCValue1 = data.Value3;
childCValue2 = data.Value4;
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct DataA
{
private int value1;
private int value2;
public int Value1 { get { return value1; } }
public int Value2 { get { return value2; } }
}
[StructLayout(LayoutKind.Sequential)]
internal struct DataB
{
private int value1;
private int value2;
private int value3;
public int Value1 { get { return value1; } }
public int Value2 { get { return value2; } }
public int Value3 { get { return value3; } }
}
[StructLayout(LayoutKind.Sequential)]
internal struct DataC
{
private int value1;
private int value2;
private int value3;
private int value4;
public int Value1 { get { return value1; } }
public int Value2 { get { return value2; } }
public int Value3 { get { return value3; } }
public int Value4 { get { return value4; } }
}
internal static class NativeMethods
{
public static void UnmanagedFunctionGetChildAData(int id, out DataA data)
{
data = new DataA();
}
public static void UnmanagedFunctionGetChildBData(int id, out DataB data)
{
data = new DataB();
}
public static void UnmanagedFunctionGetChildCData(int id, out DataC data)
{
data = new DataC();
}
}
modified 3-Jan-13 18:03pm.
|
|
|
|
|
I use a similar pattern, but instead of private member variables in the abstract base class and passing them as out parameters, I use protected member variables and call a parameterless function (the derived class may access them in other overridable functions). Visual Studio 2010 gives that CA2214 warning, too.
I feel comfortable with this pattern, and ignore the warning.
|
|
|
|
|
DaveyM69 wrote: Perhaps this code will make it clearer...
And what do you think is the problem with making the based members protected?
Or providing a protected setter for those members?
|
|
|
|
|
jschell wrote: based members protected
Non private fields are generally not considered a great idea.
jschell wrote: protected setter for those members
No problem with that, but it implies to inheriting classes that the fields that are protected by the property can be changed after initialization which is not the case - easy to protect against in code and so long as I document this well then that's OK.
|
|
|
|
|
DaveyM69 wrote: Non private fields are generally not considered a great idea.
But calling child methods in a ctor is?
DaveyM69 wrote: it implies to inheriting classes that the fields that are protected by the property can be changed after initialization
A child can misuse the contract with a parent in any number of ways. There is no way to prevent that.
|
|
|
|
|
The reason this is a warning is because you can get yourself into some really nasty messes by doing this, if you don't understand it. The virtual method that you override in the subclasses is run with an incompletely initialised object – in particular its own constructor has not yet run so you don't have access to any instance variables, even those set in a constructor or in field initialisers (as they're compiled into the constructor too).
You've obviously simplified your example a lot and in this case you can provide a protected setter for Id and create the specific data objects in the subclass constructors. I'd say that's a better approach if it's possible.
|
|
|
|
|
Yeah, that's quite possible and may be what I end up doing.
I'd like to mark the relevant fields (at least in the base) read only ideally which is primarily why I'm trying to manipulate from the constructor, along with the fact that this is all to do with construction of the objects so it is the logical place!
|
|
|
|
|
I'm making a music player in C# wpf. I have a listview which itemssource is an observable collection. The song which is currently playing is the song at the current ActiveIndex,
public int ActiveIndex { get; set; }
Not the song at the listview selected index. ActiveIndex changes only when a user double clicks a song in the listview or when he presses the next/previous buttons.
I have a style for a listview row when listview selected index changes, now I want to color the background of a row when the active index changes. I'm thinking this could somehow be done with datatriggers but I have no idea how to do it.
|
|
|
|
|
Hi. I'm probably making some subtle (or more likely not so subtle) error. I'm trying to drive MMC via a C# program. I can, as a trial, get to the menus of Calc.exe via this code:
Process calcProcess=Process.Start("c:\\windows\\system32\\calc.exe");
Thread.Sleep(2000);
AutomationElement aeDesktop = AutomationElement.RootElement;
AutomationElement aeCalc = null;
int numWaits = 0;
do
{
aeCalc = aeDesktop.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.NameProperty, "Calculator"));
Console.WriteLine("Looking for calculator . . . ");
++numWaits;
Thread.Sleep(100);
} while (aeCalc == null && numWaits < 10);
if (aeCalc == null)
throw new Exception("Failed to find calc.EXE");
else
Console.WriteLine("Found it!");
AutomationElementCollection menuCalcBars = aeCalc.FindAll(TreeScope.Children, new PropertyCondition(
AutomationElement.ControlTypeProperty, ControlType.MenuBar));
And I get a Count of 1 (for the one menu). BUT when I do this with MMC, I get a count of 0, no menu. In UISpy I can see the Calc menu but I can't see the MMC menu. Any help is GREATLY appreciated.
Ron
|
|
|
|
|
hi
I want the program to c# a folder on my system Transfer to another system in the network
|
|
|
|
|
we dont provide any programs here we provide solutions to the problems for ppl like you. None is going to write a program for you here but ready to help you when you are stuck with your programs.
you can use FileCopy[^] method to copy/move your files?
Jibesh V P
|
|
|
|
|
you will need to look into the following class
DirectoryInfo[^]
I would particularly look into the exists method for checking to see if your directory exists, getfiles so that you can look at the files that exist in the directory as you will need to implement logic if the folder and files already exist.
And as the other poster has stated you then need to look into File.Copy[^]
Lobster Thermidor aux crevettes with a Mornay sauce, served in a Provençale manner with shallots and aubergines, garnished with truffle pate, brandy and a fried egg on top and Spam - Monty Python Spam Sketch
|
|
|
|
|
Hi,
i am using .Net 2.0.
here i am using data set to retrieve value from data base and then binding it with data grid view.
but it's not displaying appropriately.
here is my code.
DataAdapter d=new DataAdapter();
select command fro data adptr.
dataSet ds=new dataSet();
d.Fill(ds);
Gridview1.datasource=ds;
gridview1.databind();
i changed auto-generate property of gridview to true also..
|
|
|
|
|
did you check the table has any rows in it?
Jibesh.V.P
India
|
|
|
|
|
yes...
data set is displaying just above the GridView.
with the specific records...
but not inside the GridView....
|
|
|
|
|
can you copy the screen shot of the screen ?
Jibesh V P
|
|
|
|
|
i took screen shoot then only...but was not there.
please tell me hw to post screen shoot
|
|
|
|
|
you can use any free image hosting site. try this[^]
Jibesh V P
|
|
|
|
|