C#中的伪朋友类

时间:2018-10-30 16:04:36

标签: c#

由于C#不提供用于朋友函数和类的机制,如果我不将代码分发到单独的程序集中并且不能总是使用嵌套类,则内部关键字无济于事,我想到了:

public sealed class FriendlyClass
{
private readonly string SecretKey = "MySecretKey";
public string PublicData { get; set; }
private string privateData;

public FriendlyClass()
{
    PublicData = "My public data";
    privateData = "My Private Data";
}

public string GetPrivateData(string key = null)
{
    if (key == SecretKey)
        return privateData;
    else throw new System.InvalidOperationException("You can't call this method directly.");

    return null;
}

public void  SetPrivateData(string newData, string key = null)
{
    if (key == SecretKey)
        privateData = newData;
    else throw new System.InvalidOperationException("You can't call this method directly.");
}
}

FriendlyClass friend = new FriendlyClass();

public void FriendlyMethod(string data)
{
    friend.SetPrivateData(data, "MySecretKey");
}

public void StrangerMethod(string data)
{
    friend.SetPrivateData(data);
}

FriendlyMethod("Data is changed");
StrangerMethod("Data is not changed");

这很丑陋而且要写很多东西。我的问题是:有人仍然可以滥用FriendlyClass的公共方法,使代码崩溃或产生意外行为吗?

1 个答案:

答案 0 :(得分:1)

访问修饰符不应保证数据安全,而应确保代码质量并限制调用某些方法或访问某些数据的方式。但是,即使您创建了一个将所有字段和方法都标记为私有的类,仍有一些方法允许程序员从代码中的“未授权”位置访问这些成员。反射可以被认为是这些方法之一。以下面的代码为例:

public sealed class Example
{
    private string field = "secure";

    private void PrintField()
    {
        Console.WriteLine(this.field);
    }
}

public class Program
{
    public static void Main()
    {
        var example = new Example();
        var field = example.GetType().GetField("field", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var method = example.GetType().GetMethod("PrintField", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

        field.SetValue(example, "hacked");
        method.Invoke(example, new object[] { });
        Console.ReadLine();
    }
}

即使Example类中的方法和字段都被标记为私有,Program类中的调用者也可以否决该方法,并且都可以在字段中设置值并调用方法

所以我的答案是-是的,仍然有人可以通过使用Reflection,直接内存操作等来滥用它。如果有人想“入侵”您的代码-他们仍然会这样做。没有理由让没有这样做的人变得更加艰难。我认为使用这样的伪友好类会给程序员一种错误的安全感,但代价是代码清晰度降低和使用该类所需的不必要操作的代价很高。