While I hate to beat a horse to death on this subject (I've read through various articles about this), but would just like to get more opinions on this matter before I create my "own convention" to use from now on while coding in Objective-C.
The convention that I want to figure out is ultimately how to (using best coding practices for production level code) use private methods in a class. Coming from a background in C#, when I write classes, usually there is a block of code that is repeated in multiple public methods (such as error checking, or WCF service connection setup). I usually create one block of this code and put it in a private method for only these public methods to access. This way if I need to make a change, I only need to do it in one spot, as opposed to 10 different places in a class, but then never giving users the ability to call this private method. For example:
public Class A
{
public void method1()
{
doErrorChecking()
// Do more stuff
}
public void method2()
{
doErrorChecking()
// Do more stuff
}
private doErrorChecking() { //Error Checking Code}
}
I understand that there is no real way to truly make that last method private in Objective-C, but just really want to make sure that when I create all future classes in Objective-C for iOS development I'm following the best practice available so future code refactoring on this matter won't be needed (hopefully). I've noticed people talking about categories, others just don't put the method in the #interface file, and others use extension methods. At the moment I'm just putting the method implementation in the #implementation file, but not the interface file. I'm also making the "wannabe" private method have a really distinct name so that sub-classing or overwriting methods is not an issue. Is this the path I should be following? Or for these particular scenarios is there a better way to do it?
Yes, it's perfectly reasonable to want to extract your functionality out into another method. The best way to do this in my opinion is using a class continuation, which you can put your private method declarations in. It can go above your #implementation block in your .m file, so it's not in the public header.
#interface MyClass ()
- (void)_privateMethod:(id)arg;
#end
The difference between a class continuation and a normal category (such as #interface MyClass (PrivateMethods)) is that the compiler will require you to implement the methods in your main #implementation block, rather than having a separate #implementation MyClass (PrivateMethods) block. This is arguably desirable when implementing helper methods like you described.
In terms of naming, it's relatively common to start private method names (and ivar names, for that matter) with an _, though not everyone does — apparently Apple reserves this for themselves, so you should pick a different prefix. The language doesn't enforce anything.
I would use a class extension, definitely. In the implementation file, include something like this above your #implementation:
#interface A ()
- (void) doErrorChecking;
#end
Then use the method in code as needed. Although due to objective-c's dynamic nature no method is truly private, this will obscure the method from your interface file while still technically including it in your own 'private' interface. In general, keep your .h file for methods and properties that are ok for public use, while limiting private use methods and properties to a class extension in the implementation file.
If you just need a reusable set of code that absolutely cannot be overridden by a subclass, you could just make a regular C function instead of a method. If the function is declared within the scope of the class #implementation block, it can still get access to all the private ivars of the object. You'd need to pass in a pointer to self, though, since a function isn't bound to a particular object
So it would look like this:
static BOOL isInValidState(MyClass *);
#implementation MyClass
static BOOL isInValidState(MyClass *self) {
if (self->somePrivateIvar == nil) {
return NO;
}
if ([self->someString isEqualToString:#"pigsAreFlying"]) {
return NO;
}
return YES;
}
- (void)method1 {
if (isInValidState(self) == NO) {
return;
}
// Do whatever method 1 does
}
- (void)method2 {
if (isInValidState(self) == NO) {
return;
}
// Do whatever method 2 does
}
#end
Since functions are not part of the method list of a class, this error checking method cannot ever be overridden. Since we declared it static, it is only accessible within the scope of this file, which means that it's effectively private; it cannot be called by an object of any other class.
Related
I have a superClass called Block and another 3 subclasses. the class I want to implement contains 3 overloaded functions each one takes an object of one of the subclasses as a parameter. When I use one of these function, I only have a Block object (An object from the superClass). My question is what is the cleanest way to choose which function to call.
What I did until now is if conditions on the object type then casting it. but it seems unclean.
Those are the overloaded functions.
public void WriteBlock(TableBlock block) { }
public void WriteBlock(TextBlock block) { }
public void WriteBlock(ListBlock block) { }
And This is The function I want to implement.
public void WriteBlocks(List<Block> blocks)
{
BlockWriter w = new BlockWriter();
foreach (var block in blocks)
{
w.WriteBlock(block);
}
}
Note that I have no access on the Blocks classes.
Yes, it is possible using the dynamic type which allows for this.
If you use:
foreach (var block in blocks)
{
w.WriteBlock(block as dynamic);
}
It should call the intended WriteBlock overload.
This is described in greater length in another question: https://stackoverflow.com/a/40618674/3195477
And also here: method overloading and dynamic keyword in C#.
Caveats:
I am not sure if there is any runtime penalty associated with this type of dynamic "cast".
Also whenever I see this pattern it makes me wonder if the class hierarchy could be improved. i.e., should whatever WriteBlock will do actually be moved inside the Block classes? That might be "more polymorphic". Also using dynamic could be a somewhat fragile approach, as you can add new Block derived types and forget to an an overloaded WriteBlock for them, which may cause an error. (This is more evidence that some of WriteBlock should be incorporated into the Block classes themselves).
For instance, add a virtual PrepareForWriting() to the base Block class, which returns a BlockWritable. Then you only need one WriteBlock(BlockWritable data) to do the writing work. BlockWritable could be a string, Json, XML, etc. This assumes you are able to modify the Block classes (which it seems you cannot).
No. Given this:
public void WriteBlocks(List<Block> blocks)
the only thing the compiler knows about each item in the list is that it is a Block. That's all it should know. That's what makes polymorphism possible. There can be any number of classes that inherit from Block, but within this context those distinctions don't matter.
But if all the compiler knows is that each item is a Block, it can't know whether any individual item might be a TableBlock, TextBlock, or some other inherited type. If, at compile time, it doesn't know what the runtime type will be, it can't know whether there even is an overload for that specific type.
Suppose what you're trying to do could compile, because you have an overload for every type that inherited from Block. What would or should happen if you added a new type - class PurpleBlock : Block - and there was no overload for it? Should this no longer compile just because you added a new type?
If the method that calls WriteBlocks knows what sort of Block is in the list, then it can supply that information:
public void WriteBlocks<TBlock>(List<TBlock> blocks) where TBlock : Block
Now you can call WriteBlock<TextBlock>(listOfTextBlocks) and the compiler will know that each item in the list is a TextBlock, not just a Block.
It follows, then, that BlockWriter would have to be generic also so that you could have different implementations for different types of Block. It might make more sense to inject it. Either way, you're likely to perceive that you've "moved" the problem. If the class that calls WriteBlocks "knows" the type of the Block, then it might make more sense for that method to determine the type of BlockWriter to use.
As mentioned in your comment, the list might include different types of Block, not just one. That requires either a method or a class that returns a specific BlockWriter depending on the type of Block. That means runtime type-checking, which isn't ideal, but it's not too bad if you keep it in one place.
Here's a simple example:
public class BlockWriterFactory
{
public BlockWriter GetBlockWriter(Block block)
{
if (block is TextBlock)
return new TextBlockWriter();
if (block is TableBlock)
return new TableBlockWriter();
if (block is ListBlock)
return new ListBlockWriter();
// this could be a "null" class or some fallback
// default implementation. You could also choose to
// throw an exception.
return new NullBlockWriter();
}
}
(A NullBlockWriter would just be a class that does nothing when you call its Write method.)
This sort of type-checking isn't ideal, but at least this keeps it isolated into one class. Now you can create (or inject) an instance of the factory, and call GetBlockWriter, and the rest of your code in that method still wouldn't "know" anything about the different types of Block or BlockWriter.
BlockWriter w = new BlockWriter();
would become
BlockWriter w = blockWriterFactory.GetBlockWriter(block);
...and then the rest would still be the same.
That's the simplest possible factory example. There are other approaches to creating such a factory. You could store all of your implementations in a Dictionary<Type, BlockWriter> and attempt to retrieve an instance using block.GetType().
I am working on a large project where a base class has thousands of classes derived from it (multiple developers are working on them). Each class is expected to override a set of methods. I first generated these thousands of class files with a code template that conforms to an acceptable pattern. I am now writing unit tests to ensure that developers have not deviated from this pattern. Here is a sample generated class:
// Base class.
public abstract partial class BaseClass
{
protected abstract bool OnTest ();
}
// Derived class. DO NOT CHANGE THE CLASS NAME!
public sealed partial class DerivedClass_00000001: BaseClass
{
/// <summary>
/// Do not modify the code template in any way.
/// Write code only in the try and finally blocks in this method.
/// </summary>
protected override void OnTest ()
{
bool result = false;
ComObject com = null;
// Declare ALL value and reference type variables here. NOWHERE ELSE!
// Variables that would otherwise be narrowly scoped should also be declared here.
// Initialize all reference types to [null]. [object o;] does not conform. [object o = null;] conforms.
// Initialize all value types to their default values. [int x;] does not conform. [int x = 0;] conforms.
try
{
com = new ComObject();
// Process COM objects here.
// Do NOT return out of this function yourself!
}
finally
{
// Release all COM objects.
System.Runtime.InteropServices.Marshal.ReleaseComObject(com);
// Set all COM objects to [null].
// The base class will take care of explicit garbage collection.
com = null;
}
return (result);
}
}
In the unit tests, I have been able to verify the following via reflection:
The class derives from [BaseClass] and does not implement any interfaces.
The class name conforms to a pattern.
The catch block has not been filtered.
No other catch blocks have been added.
No class level fields or properties have been declared.
All method value type variables have been manually initialized upon declaration.
No other methods have been added to the derived classes.
The above is easily achieved via reflection but I am struggling with asserting the following list:
The catch block re-throws the caught exception rather than wrapping it or throwing some other exception.
The [return (result);] line at the end has not been modified and no other [return (whatever);] calls have been added. No idea how to achieve this.
Verify that all reference types implementing IDisposable have been disposed.
Verify that all reference types of type [System.__ComObject] have been manually de-referenced and set to [null] in the finally block.
I have thought about parsing the source code but I don't like that solution unless absolutely necessary. It is messy and unless I have expression trees, almost impossible to guarantee success.
Any tips would be appreciated.
Some thoughts:
If the methods need to be overriden, why are they virtual instead of abstract?
Code that should not be changed doesn't belong in the derived class. It belongs in the base class.
catch { throw; } is useless. Remove it.
Returning a boolean value from a void method causes a compiler error.
Setting local variables to null is useless.
Not all reference types implement IDisposable.
Generally: Most of your requirements seem to have no business value.
Why prohibit implementation of an interface?
Why prohibit declaration of other methods?
Why prohibit catch clauses?
etc.
You should really think about what your actual business requirements are and model your classes after them. If the classes need to fulfill a certain contract, model that contract. Leave the implementation to the implementor.
About the actual questions raised:
You can't use reflection here. You can either analyze the original source code or the IL code of the compiled assembly.
Both options are pretty tricky and most likely impossible to achieve within your limited time. I am positive that fixing the architecture would take less time than implementing one of those options.
You could try to use Roslyn CTP here if the fully automated code analysis is what you really need. It has more advanced syntax and semantics analysis than reflection does. But it is still a lot of work. Working directly with developers, not with their code, preparing templates, guidelines may be more time efficient.
While I'm sure you have a very good reason for such rigid requirements... have you considered passing a Lambda's/Delegates/Action to the Test function instead?
Can't solve everything, but would more logically give you some of the behaviours you want (e.g. can't return, can't have class level variables, can't write code anywhere but specified).
Biggest concern with it would be captured variables... but there may be work arounds for that.
Example Code:
//I'd make a few signatures....
bool OnTest<T1, T2> (Action<ComObject, T1, T2> logic, T1 first, T2 second)
{
bool result = false;
ComObject com = null;
//no checks needed re parameters
//Can add reflection tests here if wanted before code is run.
try
{
com = new ComObject();
//can't return
logic(com, first,second);
}
finally
{
// Release all COM objects.
System.Runtime.InteropServices.Marshal.ReleaseComObject(com);
// Set all COM objects to [null].
// The base class will take care of explicit garbage collection.
com = null;
//If you want, we can check each argument and if it is disposable dispose.
if (first is IDisposable && first != null) ((IDisposable) first).Dispose();
...
}
return (result); //can't be changed
}
No idea if this'll work, but it's just a thought. Oh, and as a thought it's not thorough or tested - I'd expect you to develop it drastically.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Why doesn't C# have local static variables like C? I miss that!!
Because they screwed up, and left out a useful feature to suit themselves.
All the arguments about how you should code, and what's smart, and you should reconsider your way of life, are pompous defensive excuses.
Sure, C# is pure, and whatchamacallit-oriented. That's why they auto-generate persistent locals for lambda functions. It's all so complicated. I feel so dumb.
Loop scope static is useful and important in many cases.
Short, real answer, is you have to move local statics into class scope and live with class namespace pollution in C#. Take your complaint to city hall.
The MSDN blog entry from 2004: Why doesn't C# support static method variables? deals with the exact question asked in the original post:
There are two reasons C# doesn't have this feature.
First, it is possible to get nearly the same effect by having a
class-level static, and adding method statics would require increased
complexity.
Second, method level statics are somewhat notorious for causing
problems when code is called repeatedly or from multiple threads, and
since the definitions are in the methods, it's harder to find the
definitions.
[author: Eric Gunnerson]
(Same blog entry in the Microsoft's own archive. The Archive.org preserved the comments. Microsoft's archive didn't.)
State is generally part of an object or part of a type, not part of a method. (The exception being captured variables, of course.)
If you want the equivalent of a local static variable, either create an instance variable or a static variable - and consider whether the method itself should actually be part of a different type with that state.
I'm not nearly as familiar with C as I am C#, but I believe you can accomplish everything you could with a local static, by using a class level static that is only used for one method. Obviously, this comes with some syntactic change, but I believe you can get whatever functionality you need.
Additionally, Eric Lippert answers questions like this on his blog a lot. Generally answered in this way: "I am asked "why doesn't C# implement feature X?" all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature." Essentially his answers generally boil down to, it costs money to add any feature, and therefore, many potential features are not implemented because they have not come out on the positive side of the cost benefit analysis.
So you want to use a static local variable in your method? Congratulations! You made another step towards becoming a real programmer.
Don't listen to all the people telling you that static locals are not "clean", that they impede "readability" and could lead to subtle and hard-to-find "bugs". Nonsense! They just say that because they are wannabe programmers! Lots of them are probably even toying around with an esoteric functional programming language during their free-time. Can you believe it? What a bunch of hipsters!
Real programmers embrace a paradigm I like to call SDD - Side effect Driven Design. Here are some of it's most important laws:
Don't be predictable! Never return the same thing from a method twice - even if it's being called with the exact same arguments!
Screw purity - let's get dirty! State, by nature, craves changing, because it is an insatiable monoid in the category of polyamorous endofunctors, i.e. it likes to be touched by as many collaborators as possible. Never miss out on an opportunity to do it the favor!
Among the tools used to code in a side effect driven manner are, of course, static local variables. However, as you noticed, C# does not support them. Why? Because over the last two decades Microsoft has been infiltrated by so called Clean Coders that favor maintainability over flexibility and control. Can you even remember the last time you have seen our beloved blue screen? Now guess whose fault is that!
But fear not! Real developers don't have to suffer from those poor design decisions. As has been mentioned before it is possible to have local variables that are kind of static with the help of lambdas.
However, the provided solution wasn't quite satisfactory. Using the previous answer our almost-SDD-compliant code would look something like this:
var inc = Increment();
var zero = inc();
var one = inc();
or
var zero = Increment()();
But that's just silly. Even a wannabe developer can see that Increment() is not a normal method and will get suspicious. A real programmer, on the other hand, can make it even more SDD-like. He or she knows that we can make a property or field look like a method by giving it the type Func<T>! We just have to initialize it by executing a lambda that in turn initializes the counter and returns another lambda incrementing the captured counter!
Here it is in proper SDD code:
public Func<int> Increment = new Func<Func<int>>(() =>
{
var num = 0;
return () => num++;
}).Invoke();
(You think the above kinda looks like an IIFE? Yes, you are right and you should be ashamed of yourself.)
Now every time you call Increment() it will return something different:
var zero = Increment();
var one = Increment();
Of course you also can make it so that the counter survives the lifetime of your instance.
That'll show them wannabe programmers!
C# is a component-oriented language and doesn't have the concept of variables outside the scope of a class or local method. Variables within a method cannot be declared static either, as you may be accustomed to doing in C. However, you can always use a class static variable as a substitute.
As a general practice, there are usually ways to solve programming problems in C# without resorting to using method-level statics. State is generally something you should design into classes and types, not methods.
Logically, yes. It would be the same as a class-level static member that was only used in that one method. However, a method-level static member would be more encapsulated. If the data stored in a member is only meant to be used by a single method, it should only be accessible by that single method.
However, you CAN achieve almost exactly the same effect in C# by creating a nested class.
Because static local variables are tied to the method, and the method is shared amongst all instances.
I've had to correct myself and other programmers who expect it to be unique per class instance using the method.
However, if you make it a static class, or static instance of a class, it's syntactically clear whether there's an instance per container-class, or one instance at all.
If you don't use these, it becomes easier to refactor later as well.
I think the idea of local statics is just as easily solved by creating public static fields to the class. Very little logical change don't you think?
If you think it would be a big logical change, I'd be interested to hear how.
class MyClass
{
public static float MaxDepthInches = 3;
private void PickNose()
{
if (CurrentFingerDepth < MyClass.MaxDepthInches)
{
CurrentFingerDepth++;
}
}
}
You can use nested-class as a workaround for this. Since C# is limiting the scope of static variables to classes, you can use nested-class as a scope.
For example:
public class Foo {
public int Increment() {
return IncrementInternal.Increment();
}
private static class IncrementInternal {
private static int counter = 0;
public static int Increment() {
return counter++;
}
}
}
Here Foo supports Increment method, but its support it by the private nested class IncrementInternal which contains the static variable as a member. And of course, counter is not visible in the context (other methods) of Foo.
BTW, if you want to access to Foo context (other members and methods) inside IncrementInternal.Increment, you can pass this as a parameter to IncrementInternal.Increment when you call it from Foo.
To keep the scope as small as possible, my suggestion is to create a nested class per each such method. And because it is probably not so common, the number of nested classes will stay small enough to maintains it.
I think it is cleaner than anonymous functions or IIFE.
You can see a live demo here.
I don't see much added benefit to local statics, if you are keeping your classes single purpose and small, there is little problem with global static pollution as the naysayers like to complain about. But here is just one other alternative.
using System;
using System.Collections;
public class Program
{
delegate bool DoWork();
public static void Main()
{
DoWork work = Foo().GetEnumerator().MoveNext;
work();
work();
work();
}
public static IEnumerable Foo()
{
int static_x = 10;
/*
do some other static stuff....
*/
main:
//repetative housework
Console.WriteLine(static_x);
static_x++;
yield return true;
goto main;
}
}
If you can imagine some sort of Lippert/Farnsworth hybrid entity announcing GOOD NEWS EVERYONE!, C# 6.0 allows the using static statement. This effectively allows you to import static class methods (and, it seems, properties and members as well) into the global scope.
In short, you can do something like this:
using NUnit.Framework;
using static Fizz.Buzz;
class Program
{
[Test]
public void Main()
{
Method();
int z = Z;
object y = Y;
Y = new object();
}
}
namespace Fizz
{
class Buzz
{
public static void Method()
{
}
public static int Z;
public static object Y { get; set; }
}
}
While this is only available in C# 6.0, from what I understand the generated assemblies should be compatible with previous .NET platforms (correct me if I'm wrong).
You can simulate it using a delegate... Here is my sample code:
public Func<int> Increment()
{
int num = 0;
return new Func<int>(() =>
{
return num++;
});
}
You can call it like this:
Func<int> inc = Increment();
inc();
I have a question that's not really a problem, but something that made me a little curious.
I have a class with two methods in it. One is a static method and the other one is an instance method. The methods have the same name.
public class BlockHeader
{
public static BlockHeader Peek(BinaryReader reader)
{
// Create a block header and peek at it.
BlockHeader blockHeader = new BlockHeader();
blockHeader.Peek(reader);
return blockHeader;
}
public virtual void Peek(BinaryReader reader)
{
// Do magic.
}
}
When I try to build my project I get an error saying:
The call is ambiguous between the
following methods or properties:
'MyApp.BlockHeader.Peek(System.IO.BinaryReader)'
and
'MyApp.BlockHeader.Peek(System.IO.BinaryReader)'
I know that the method signatures are virtually the same, but I can't see how I possibly could call a static method directly from an instance member.
I assume that there is a very good reason for this, but does anyone know what that reason is?
The general policy of the C# design is to force you to specify wherever there is potential ambiguity. In the face of refactoring tools that allow one to rejig whether things are static or not at the drop of a hat, this stance is great - especially for cases like this. You'll see many other cases like this (override vs virtual, new for shadowing etc.).
In general, removing this type of room for confusion will make the code clearer and forces you to keep your house in order.
EDIT: A good post from Eric Lippert discusses another reason for this ambiguity leading to the error you saw
Here's a excerpt from the C# 3.0 language specification.
The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. The signature of a method does not include the return type.
The 'static' modifier is not part of the signature so your example violates this rule of unique signatures.
I don't know the reason behind the rule, though.
I think there's no technical reason to disallow it, but it is done more so to protect the programmer from himself. Consider the following example:
public static void Main()
{
BlockHeader BlockHeader = new BlockHeader();
BlockHeader.Peek();
}
The example above is perfectly valid, but if the situation you describe were allowed, would it be readable? Could you see, in the blink of an eye, whether the instance method or the static method was called?
Is there a way via System.Reflection, System.Diagnostics or other to get a reference to the actual instance that is calling a static method without passing it in to the method itself?
For example, something along these lines
class A
{
public void DoSomething()
{
StaticClass.ExecuteMethod();
}
}
class B
{
public void DoSomething()
{
SomeOtherClass.ExecuteMethod();
}
}
public class SomeOtherClass
{
public static void ExecuteMethod()
{
// Returns an instance of A if called from class A
// or an instance of B if called from class B.
object caller = getCallingInstance();
}
}
I can get the type using System.Diagnostics.StackTrace.GetFrames, but is there a way to get a reference to the actual instance?
I am aware of the issues with reflection and performance, as well as static to static calls, and that this is generally, perhaps even almost univerally, not the right way to approach this. Part of the reason of this question is I was curious if it was doable; we are currently passing the instance in.
ExecuteMethod(instance)
And I just wondered if this was possible and still being able to access the instance.
ExecuteMethod()
#Steve Cooper:
I hadn't considered extension methods. Some variation of that might work.
Consider making the method an extension method. Define it as:
public static StaticExecute(this object instance)
{
// Reference to 'instance'
}
It is called like:
this.StaticExecute();
I can't think of a way to do what you want to do directly, but I can only suggest that if you find something, you watch out for static methods, which won't have one, and anonymous methods, which will have instances of auto-generated classes, which will be a little odd.
I do wonder whether you should just pass the invoking object in as a proper parameter. After all, a static is a hint that this method doesn't depend on anything other than its input parameters. Also note that this method may be a bitch to test, as any test code you write will not have the same invoking object as the running system.
I do not believe you can. Even the StackTrace and StackFrame classes just give you naming information, not access to instances.
I'm not sure exactly why you'd want to do this, but know that even if you could do it it would likely be very slow.
A better solution would be to push the instance to a thread local context before calling ExecuteMethod that you can retrieve within it or just pass the instance.
In the case of a static method calling your static method, there is no calling instance.
Find a different way to accomplish whatever you are trying to do.
Just have ExecuteMethod take an object. Then you have the instance no matter what.
I feel like I'm missing something, here. The static method can be called from literally anywhere. There's no guarantee that a class A or class B instance will appear anywhere in the call stack.
There's got to be a better way to accomplish whatever you're trying to do.